简体   繁体   中英

Best way to import python module at the root of a package hierarchy from another module in the same package

I write a package P. At the root of P there is a module m0. Somewhere inside P there are modules m1,m2,... that need to import from m0

Of course I can write in each of these modules:

from P.m0 import ...

However if I change the name of PI have to revisit all the places and rewrite such statements.

I could also use relative imports but if I move a module at a different level in the package hierarchy I have to go fix the number of dots.

There are some other reasons too, but bottom line, I really want to say import from the module m0 that is located at the root of my package, what is the best way to express this?

That's not possible.

However, if you perform major refactoring where you move around modules between subpackages having to update some relative imports is not a huge problem.

Same applies for renaming the top-level package name if you do not use relative imports - that could even be done really fast with search-and-replace over all your files.

If you are willing to modify your question a tiny bit, you can get away with this.

IF the only entrypoints to your package are controlled; eg you only test your code by doing something like invoking testsuite package/.../module.py which will

THEN you can make sure that the first thing you do is import firstthing , and in package/firstthing.py you have:

import sys
import os.path
packageDir = os.path.split(__name__)[0]
sys.path[:] = sys.path+[packageDir]  # or maybe you want it first...

The main caveat being that you will not be able to run python files without going through your entrypoints. I always want to do this for every project I write in python (to make relative imports work nicely), but I personally find this so inconvenient that I just give up.


There is also a second alternative. It is not that unreasonable to specify that your package requires another package in the python path. This package could be a utility package which performs a major hack. For example if the name of the package was "x", you could do import x which would use the inspect module to perform reflection on the interpreter stack, letting you figure out which module you were importing it from. Then you could do a sort of "backwards os.walk" by going up parent directories until you found the root of your package (by checking for some special indicator file, or manifest, or something). Then the code would programatically perform the above modification of the python path via sys.path . It's the same as the above, but you have the liberty to do things like run any python file without having to go through an awful entrypoint.

If you have extreme control over the shell environment, you can also just augment the $PYTHONPATH to include your package directory, but this is extremely fragile in many ways, and rather inelegant.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM