I have the following structure of python code:
.
├── my_main.py
└── my_pkg
├── my_dep.py
├── my_script.py
Both my_main.py
and my_script.py
should be callable (have a if __name__ == '__main__'
) section:
my_main.py:
import my_pkg.my_script
if __name__ == '__main__':
print(my_pkg.my_script.bar())
and my_script.py:
import my_dep
def bar():
return my_dep.foo() + 1
if __name__ == '__main__':
print(bar())
this imports... my_dep.py: , which looks like:
def foo():
return 1
If you want to look at it all together, look here: https://github.com/ct2034/python_import_trouble
Problem:
If I run my_script.py
, all works well.
But if I run my_main.py
, I get:
ModuleNotFoundError: No module named 'my_dep'
If I change the import in my_script.py
to from. import my_dep
from. import my_dep
, my_main.py
works.
But when I run my_script.py
, I get:
ImportError: attempted relative import with no known parent package
How can I make both of them work?
Note: This is on Python 3.8
And sorry for the long-winded explanation. Was not able to make it any more concise. Hope it is understandable.
Both my_main.py and my_script.py should be callable (have a if name == ' main ') section)
No they should not.
What you want to do is a non Pythonic design, and even if you manage to achieve it with some work you will later be bitten. And the later is the worse because it could break more things including in production code.
I strongly urge you to stick to the common rules:
sys.path
It will indeed force you to adapt your design, but it will work smoothly and could easily be packaged into a distribution.
My advice if you have multiple related modules is to design that as a package (with __init__.py
files). You will then get natural relative imports.
If you additionaly need to start scripts, you can either build wrapper scripts using the package modules or use a __main__.py
file in your top level package folder: it will be executed if your run python -m package
. But please, please do not try to run the same file sometimes as a package module and sometimes as a script. Or at least do not expect me to help you on that way...
I found a way to make it work. Serge is absolutely right in saying that this should be done differently altogether ( https://stackoverflow.com/a/70594758/1493204 ). But if you still want it, this is how to do it:
my_script.py :
if __name__ != '__main__':
from . import my_dep
def bar():
return my_dep.foo() + 1
if __name__ == '__main__':
import my_dep
print(bar())
also here.. https://github.com/ct2034/python_import_trouble/tree/bad_solution
From the directory level of my_main.py
you can call the script with python -m mypkg.my_script
.
If this is meant to become an installable package, you can use the setup.py
to create entry points or scripts, which will be installed into some system wide accessible bin
directory anyway.
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.