简体   繁体   中英

Python3 relative imports failing in package

I've been reading tons of questions related to this matter but none of the has help me so far. I'm currently using the Python click library to execute scripts as commands.

The current command that I'm trying to execute is placed inside a Python Package which has a __main__.py file, like the parent dir has. The current project structure is the following one.

/myproject
   /foo_one
       __init__.py
       foo_one.py
    /foo_two
       __init__.py
       foo_two.py
    /foo_three
       __init__.py
       foo_three.py
    /foo_four
       __init__.py
       foo_four.py
    /foo_five
       __init__.py
       foo_five.py
    /foo_six
       __init__.py
       foo_six.py
    __init__.py
    __main__.py
    foo_seven.py

Whenever I try to run the __main__.py script located in the project folder, the following error comes up.

ModuleNotFoundError: No module named '__main__.foo_two'; '__main__' is not a package

However, if I try to execute that same script from a folder above with the -m option like this python3 myproject -m , the following is shown up.

ImportError: attempted relative import with no known parent package

The __main__.py has 2 imports like this... The __init__.py is empty.

from .foo_two.foo_two import AClass, AnotherClass, OtherClass
from .foo_three.foo_three import AnotherClassMore

UPDATE : Correcting the syntax error in a previous command, while calling python -m myproject gives me a ModuleNotFoundError because of a module that isn't my responsibility, which is basically a library that is used in the project.

The correct syntax would be

python -m myproject

This should execute __main__ in the top-level package.

Hopefully, this will be of value to someone out there - I went through half a dozen stackoverflow posts trying to figure out relative imports similar to whats posted above here. I set up everything as suggested but I was still hitting ModuleNotFoundError: No module named 'my_module_name'

Since I was just developing locally and playing around, I hadn't created/run a setup.py file. I also hadn't apparently set my PYTHONPATH .

I realized that when I ran my code as I had been when the tests were in the same directory as the module, I couldn't find my module:

$ python3 test/my_module/module_test.py                                                                                                               2.4.0
Traceback (most recent call last):
  File "test/my_module/module_test.py", line 6, in <module>
    from my_module.module import *
ModuleNotFoundError: No module named 'my_module'

However, when I explicitly specified the path things started to work:

$ PYTHONPATH=. python3 test/my_module/module_test.py                                                                                                  2.4.0
...........
----------------------------------------------------------------------
Ran 11 tests in 0.001s

OK

So, in the event that anyone has tried a few suggestions, believes their code is structured correctly and still finds themselves in a similar situation as myself try either of the following if you don't just add your export the current directory to your PYTHONPATH:

  1. Run your code and explicitly include the path like so: $ PYTHONPATH=. python3 test/my_module/module_test.py $ PYTHONPATH=. python3 test/my_module/module_test.py
  2. To avoid calling PYTHONPATH=. , create a setup.py file with contents like the following and run python setup.py development to add packages to the path:
 # setup.py from setuptools import setup, find_packages setup( name='sample', packages=find_packages() ) 

You need to have __init__.py in each sub folder with python code to tell the interpreter to treat the folder as a module

/myproject
   /foo_one
       __init__.py # add this
       foo_one.py
    /foo_two
       __init__.py # add this
       foo_two.py
    /foo_three
       __init__.py # add this
       foo_three.py
    /foo_four
       __init__.py # add this
       foo_four.py
    /foo_five
       __init__.py # add this
       foo_five.py
    /foo_six
       __init__.py # add this
       foo_six.py
    __init__.py
    __main__.py
    foo_seven.py

the __init__.py is telling the interpreter to treat sub folders as python modules / packages and you should be able to import

The __init__.py file can be empty but needs to be present in the sub folders to be able to import that module / package

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