blong
blong

Reputation: 2713

Simple migration to __init__.py

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

Answers (2)

Mark Ignacio
Mark Ignacio

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

user2455127
user2455127

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

Related Questions