0

I'm trying to understand the import-logic in Python.

If you take this tutorial as a reference, I think you won't be able to, for example state:

from sound.effects import echo

At least, not from within the package.

However, Suds (a package I'm interested in) does something like that here

A fragment of suds/suds/builder.py:

from logging import getLogger
from suds import * 
from suds.sudsobject import Factory
..

folder structure:

suds/
    ...no_package_init_file_here...
    suds/
        __init__.py
        builder.py
        sudsobject.py
        ...
       

How, and why does this work?

I thought it was kind-of 'not-allowed' to use the container package name within the package. As a rule of thumb.

Now, there is one thing I can think of: suds will add itself to the PYTHONPATH and thereby becomes accessible to every level. Is that the reason?

And, do you guys think that Suds has a smart solution here? Or is a bit hacky?

Thanks in advance.

Community
  • 1
  • 1
hsmit
  • 3,906
  • 7
  • 34
  • 46

2 Answers2

0

both solutions are supported. from within a package you can use:

from mypackage import mymodule

or

import mymodule

and if you just want to import a single class from a module

from mypackage import mymodule.myclass

or

import mymodule.myclass
RutledgePaulV
  • 2,568
  • 3
  • 24
  • 47
  • can you show your folder structure and the python file that is calling it? I think it's all relative. – hsmit Jul 10 '13 at 19:05
  • I think it will return a `ImportError: No module named mypackage` if this was called from mypackage/mytest.py. – hsmit Jul 10 '13 at 19:13
  • why don't you test it instead of saying 'I think it will...' – RutledgePaulV Jul 10 '13 at 19:19
  • I tested it, and in fact I get the ImportError mentioned before. However, I think it depends on the package structure you have in mind. I think it only works when the calling script is next to (thus outside) 'mypackage'. It gives an error when in the package (e.g. mypackage/mytest.py) – hsmit Jul 10 '13 at 19:24
  • That's not correct. It works perfectly fine from within that package. say mypackage contains mytest.py and mytest2.py, you can import mypackage.mytest from inside of mytest2 – RutledgePaulV Jul 10 '13 at 19:53
  • as long as mypackage contains a `__init__.py` – RutledgePaulV Jul 10 '13 at 19:53
  • OK, doing the following: `cd mypackage; python mytest.py` Is that different than what you are doing? – hsmit Jul 10 '13 at 20:00
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/33225/discussion-between-paul-r-and-hsmit) – RutledgePaulV Jul 10 '13 at 20:00
0

sounds like pythonpath..

After studying this a bit, I found out it all depends on the PYTHONPATH or sys.path. So, from sound.effects import echo works from within the sound package (first example) when sound is found in sys.path. And that only happens if sound is located in a directory that exists in sys.path.

relative to executed script

When the executed script (.py file or interpreter) is called from a directory where the sound package can be found, not errors are raised. This is because that directory is the first element in the sys.path list. But, when the executed script is inside the package itself, it won't find sound and therefore a ImportError: No module named sound will be raised. Unless of course, sound is included at another level of sys.path (for example in /usr/lib/python2.6/dist-packages).

about suds

Now, for suds this import statement was correct. And that is because the suds package exists in the PYTHONPATH (sys.path). In that way, the from suds.sudsobject import Factory calls the version of suds in PYTHONPATH (dist-packages).

extra:

In my case, I wanted to modify suds source code and therefore I placed a copy of the entire dir in my lib: my_package/lib/suds/. The calling script (.py) could however not find suds because it was 1 level too deep. And then import errors were raised because suds could not be loaded properly

When you don't want suds in/from the dist-packages you can add it to sys.path manually:

import sys, os
suds_parent = os.path.join(os.path.dirname(__file__), 'lib')
if suds_parent not in sys.path:
    sys.path.append(suds_parent)
taper
  • 9,236
  • 5
  • 28
  • 29