Search code examples
pythonpackagedirectory-structure

How do I manually refactor a python project?


As I'm learning more and more about how not to structure a coding project, I'm realizing I have to move a lot of things around to get them in the right places.

For example, I have a "practice data science" project that I'm just dumping all sorts of unrelated code into. My directory looks like this:

 - PyCharm Projects
     - data-science-at-home
         - birth_names.py
         - birthplots.py
         - genedata.py
         - etc.

Now, I am learning about separating your code into "packages" that are related modules (.py files, right?).

So in my IDE (PyCharm) I created a new packages and then move refactored my .py files to them:

 - PyCharm Projects
     - data-science-at-home
         - birth-names
             - birth_names.py
             - birthplots.py
         - package_genestuff
             - genedata.py

So what I found is that all of my code is still compiling and running as expected, but at the top of my graphingutility.py file, where I import birthnames as bn, I am getting a no module named birthnames error. For some reason, everything is compiling and the module that supposedly does not exist is being used repeatedly, but that error popup is really annoying.

I noticed that move refactor only works about half the time, and seems to cause a lot of problems when it does work. Perhaps doing this kind of thing manually would be better, but I don't understand the inner workings of all the xml, config and git files that seem to get changed every time I twitch a finger... What is the appropriate way to get this done?

EDIT: As requested, the actual code:

import birth_names as bn
import matplotlib.pyplot as plt


def myPlotter(ax, data1, data2, param_dict):
    out = ax.plot(data1, data2, **param_dict)
    return out


def plotRankAndScores(name, gender):

    files = bn.getPaths()
    print(files)
    x1, y1 = bn.getAllRanks(name, gender, files)
    x2, y2 = bn.getAllScores(name, gender, files)
    ave = bn.getAverageRank(name, gender, select=False, filez=files)

    # fig, (ax1, ax2) = plt.subplots(2, 1)
    # myPlotter(ax1, x1, y1, {'linestyle': '-.', 'color': 'red'})
    # myPlotter(ax2, x2, y2, {'linestyle': '--'})

    fig2, (ax3, ax4) = plt.subplots(2, 1, sharex='all', figsize=(10, 10))
    plt.xlabel("Year")
    ax3.plot(x1, y1, 'b')
    ax3.set_ylabel("Rank")
    ax3.axhline(y1.mean(), label='average = {}'.format(ave), linestyle='--', color='red')
    ax3.legend()
    ax4.plot(x2, y2, 'b')
    ax4.set_ylabel("Number of Births")
    ax4.axhline(y2.mean(), label='average = {}'.format(y2.mean()), linestyle='--', color='red')
    ax4.legend()
    plt.suptitle("Name Rank and Number of Births by Year")
    plt.show()


if __name__ == '__main__':
    plotRankAndScores("Wesley", "M")

Solution

  • Change the top line to this: from . import birth_names as bn

    Explanation: In english, the above line means: from the directory in which this script is located, import the file 'birth_names' with the name 'bn'

    The . indicates the local directory.