简体   繁体   中英

Import a module from a directory (package) one level up

What is the right way in Python to import a module from a directory one level up? The directory is a Python package with all these modules and I have a sub directory with code that needs these modules.

The following works just fine, but that is just a hack. I'd like a recommended / pythonic way.

import sys
sys.path.append("../")
from fruit import Fruit
print("OK")

The directory structure:

pkg1
   __init__.py  
   fruit.py  
   +sub_pkg
      __init__.py
      recipe.py

contents of fruit.py

class Fruit:
   def get_name(self):
       print("Fruit name")

contents of sub_pkg/recipe.py .. just a single import line:

from fruit import Fruit

When I run :

python recipe.py

it gives the following error.

Traceback (most recent call last):
  File "recipe.py", line 2, in <module>
    from fruit import Fruit
ImportError: No module named fruit

I also tried: from pkg1.fruit import Fruit , does not work. Also looked at other similar questions .. python -m recipe.py or python -m sub_pkg/recipe.py did not work.

In your main file recipe.py add pkg1 path to the PYTHONPATH

sys.path.append('/path/to/pkg1')

Or use a relative path

sys.path.append('../..')

This should allow importing pkg1 from any where in your program.

There is always the option of using relative imports as suggested here, I find using absolute imports more readable and less likely to lead to bugs. Also, in large projects using relative imports will have you constantly calculating path hierarchies while when using absolute imports, it's simple to know you always refer to one root directory.

About relative imports from PEP328 in Python 2.5:

Reading code which relies on relative imports is also less clear, because a reader may be confused about which module is intended to be used. Python users soon learned not to duplicate the names of standard library modules in the names of their packages' submodules, but you can't protect against having your submodule's name being used for a new module added in a future version of Python.


Guido is suggesting using leading dots in relative imports to avoid ambiguous imports as described above, from PEP328 again:

Guido has Pronounced that relative imports will use leading dots. A single leading dot indicates a relative import, starting with the current package. Two or more leading dots give a relative import to the parent(s) of the current package, one level per dot after the first.

If you're having issues you can use the following also.

This imports from current directory

from . import something

this import from one directory above

from .. import fruit

Doc for relative path: https://docs.python.org/2/tutorial/modules.html#intra-package-references

RELATIVE PACKAGE ISSUE ValueError: Attempted relative import in non-package

For people having issues with the relative package. Here's your solution.

if __name__ == "__main__" and __package__ is None:
    __package__ = "expected.package.name"

Also the explanation, copied from another python docs

When the main module is specified by its filename, then the package attribute will be set to None . To allow relative imports when the module is executed directly, boilerplate similar to the following would be needed before the first relative import statement:

if __name__ == "__main__" and __package__ is None:
    __package__ = "expected.package.name

Note that this boilerplate is sufficient only if the top level package is already accessible via sys.path . Additional code that manipulates sys.path would be needed in order for direct execution to work without the top level package already being importable.

Doc for creating packages I'm not going to paste the content since it's rather long, but here's the section on the python docs for creating packages. https://docs.python.org/2/tutorial/modules.html#packages

One more docs on PYTHONPATH https://docs.python.org/2/using/cmdline.html#envvar-PYTHONPATH

您可以使用相对导入

from ..fruit import Fruit

Instead of using upper imports, have an entry point that you can call from the upper most level and have your imports relative to that entry point in your recipe.py file.

Ex:

pkg1/
   __init__.py  
   main.py
   fruit.py  
   +sub_pkg
      __init__.py
      recipe.py

Where main.py contains:

#!/usr/bin/env python3

import subpkg.recipe as recipe
import fruit

if __package__ is None and __name__ == "__main__":
    __package__ = "main"
    print()
    # Call recipe.py or fruit.py methods from here

And in recipe.py :

import fruit
# do stuff with fruit module, which is properly imported now

To run, call python3 main.py

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