How do I avoid users of my code having to type red

2019-09-17 09:09发布

问题:

So I have a project called "Pants" that lives on GitHub.com. Originally the project was a single .py file called pants.py.

Pants/
    pants.py
    README.md

and users could import and use it as follows:

import pants
w = pants.World()

Both of these feel fine to me. Then I read up on how to structure a project with unit tests included, and initially reorganized my project thusly:

Pants/
    pants.py
    README.md
    test/
        __init__.py
        test_world.py
        test_ant.py

The problem with this is that although users can still import the same logical way, there is no pants.test module/package! No problem, I thought, I'll simply add another __init__.py file:

Pants/
    __init__.py
    pants.py
    README.md
    test/
        __init__.py
        test_world.py
        test_ant.py

But now the imports feel incredibly repetitive:

import Pants.pants
w = Pants.pants.World()

It just feels like there is a better way! Right now, my project is structured like this:

Pants/
    README.md
    pants/
        __init__.py
        ants.py
        world.py
        solver.py
        test/
            __init__.py
            test_world.py
            test_ant.py

However, the import lines users are faced with are equally repetitive:

import pants.world
import pants.solver
w = pants.world.World()
s = pants.solver.Solver()

Now I know you can alias these things to shorter equivalents, such as import pants.world.World as World but the import line itself still feels repetitive. Any suggestions on how to avoid such repetition while retaining proper project structure? Does any of this have to change if I were to, say, put it up for installation via pip?

回答1:

To fix it, I kept my package structure the same, and added the following lines to pants/__init__.py:

from .ant import Ant
from .world import World
from .solver import Solver

Then I was able to change the import lines at the top of my demo file to:

from pants import World
from pants import Solver


回答2:

Instead of having a separate pants.py put that code inside of __init__.py. Then when someone does import pants it loads that __init__.py. (I'd avoid using the uppercase "Pants" as uppercase is generally for classnames)

If your users need world or solver separately you can also do

from pants import world,solver
w = world.World()
s = solver.Solver()

If they wanted everything from your package they could do

from pants import *