简体   繁体   中英

Importing a module in sibling dir while being executed as a __main__ program

On Python 2.7 I have the following:

$ tree dir1
dir1
├── __init__.py
├── __init__.pyc
├── dir2
│   ├── File1.py
│   ├── File1.pyc
│   ├── __init__.py
│   └── __init__.pyc
└── dir3
    ├── File2.py
    ├── File2.pyc
    ├── __init__.py
    └── __init__.pyc

2 directories, 10 files



$ cat dir1/dir2/File1.py
print  __name__ + " imported successfully"
def fun():
    print "fun"

$ cat dir1/dir3/File2.py #case1
if __name__ != '__main__':
    from dir1.dir2 import File1
    print "worked"
else:
    from ..dir2 import File1

or

$ cat dir1/dir3/File2.py #case2
if __name__ != '__main__':
    from dir1.dir2 import File1
    print "worked"
else:
    from dir1.dir2 import File1

$ pwd
/Users/abc
$ python
Python 2.7.6 (default, Sep  9 2014, 15:04:36)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dir1.dir3.File2
dir1.dir2.File1 imported successfully
worked

But when I do:

$ python dir1/dir3/File2.py #case1
Traceback (most recent call last):
  File "dir1/dir3/File2.py", line 5, in <module>
    from ..dir2 import File1
ValueError: Attempted relative import in non-package

or

$ python dir1/dir3/File2.py #case2
Traceback (most recent call last):
  File "dir1/dir3/File2.py", line 5, in <module>
    from dir1.dir2 import File1
ImportError: No module named dir1.dir2

Why the error and what are the non-hacky, pythonic, standard ways of doing this?

Since you have init .py, the whole thing becomes a module at the dir1 level.

So you can use relative imports:

from ..dir2 import File1

However, this would occur by importing it at the package level, at the dir1 level. If you aren't going to use a package as a package, you need something "hacky". And by hacky, we just mean telling it where to actually import the directory. Just add it to sys.path, you can pop it later (if you are worried about the path becoming too crowded for some reason). Otherwise, there is nothing to guide the import: it cannot rely on the package interface within a "non-package", since you are not using the package as one.

Import the module and then just have file2 import as follows.

If there was no init .py or you don't want to execute it at the package level, so one way would be just to add the dir1 directory to the path and then import the file and the names inside.

Example:

import os
import sys

FILE = os.path.realpath(__file__)
HOME = os.path.dirname(FILE)
sys.path.append(HOME)

from dir2 import File1

You could also use relative paths, and just simply do:

import sys

sys.path.append('..')

from dir2 import File1

Read the Intra Package References from the tutorial. It says

Note that both explicit and implicit relative imports are based on the name of the current module. Since the name of the main module is always " main ", modules intended for use as the main module of a Python application should always use absolute imports.

So relative imports would not work. You need to make sure your package dir1 is in the PYTHONPATH and then you do:

from dir1.dir2 import File1

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