Reputation: 2713
I'm upgrading a bunch of scripts where the ecosystem is a bit of a mess. The scripts always relied on external modules, and didn't have any package infrastructure of their own (they also didn't do much OOP, as you can imagine). There's nothing at the top level, but it is the working directory when starting Python and I'd like to keep it that way. At the top-level, I've just created __init__.py
file (based on another question). As I'm less experienced with Python __init__.py
confuses me a bit. All of the __init__.py
files I've created are empty, it's my understanding that this is all that's required.
Assume I have the following directory structure:
__init__.py
dev.properties
prod.properties
F/
Foo.py
__init__.py
B/
bar.py
__init__.py
And the code is like this :
# Foo.py
from ..b import bar
barFunc()
# bar.py
def barFunc():
print "Hello, World!"
sys.stdout.flush()
I've created __init__.py
at the root, in F/
and in B/
. However, when I run python F/Foo.py
, I get an error:
Traceback (most recent call last):
File "F/Foo.py", line 3, in <module>
from ..b import bar
ValueError: Attempted relative import in non-package
What exactly would I need to do to invoke python F/Foo.py
and be able to depend on things defined in sibling directories?
Update
Thanks to @user2455127, I realized that I forgot to remove the file extension .py
and my working directory was wrong. From the mypackage
directory, running python -m mypackage/F/Foo
, the error was : myvirtualenv/bin/python: No module named mypackage/B/bar
.
Re-reading @user2455127's post, I ran from the directory above and get a long Traceback:
Traceback (most recent call last):
File "/usr/lib/python2.7/runpy.py", line 162, in _run_module_as_main
"__main__", fname, loader, pkg_name)
File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
exec code in run_globals
File "<full path>/mypackage/foo/Foo.py", line 24, in <module>
from ..b import bar
ValueError: Attempted relative import in non-package
I'm not quite sure what needs to be done to fix this, but it seems like the __package__
attribute may help. I'll try and figure that out, and post another update.
Upvotes: 0
Views: 956
Reputation: 441
If the current working directory is F's and B's parent directory, then F and B are available as modules to all Python code. You should run:
$ F/foo.py
and then F/foo.py
should contain
from B.bar import barFunc
barFunc()
As for __init__.py
, that file's existance simply makes the directory an importable module. If you want to know more about it, check the docs on how imports work. (For most people, reading all of that isn't necessary.)
Relative imports can be pretty messy, so I'd advise shying away from them for now.
Upvotes: 1
Reputation: 51
Have a look to this : Attempted relative import in non-package even with init.py and brenBarn's answer
If you run it from the folder upper than the one with dev.properties and the others files (called lambda in my case), with this command line :
python -m lambda.F.Foo
it works.
Upvotes: 1