ImportError depending on the calling module

S

Samuel

Hi,

Given the following directory structure:

---------
|-- Obj.py
|-- __init__.py
|-- foo
| |-- FooTest.py
| `-- __init__.py
`-- start1.py
---------

With the following content:

---------
$ cat Obj.py
class Obj(object):
pass

$ cat __init__.py
import Obj
__all__ = ['Obj']

$ cat foo/FooTest.py
from Obj import Obj

class FooTest(object):
pass

$ cat foo/__init__.py
from FooTest import FooTest
__all__ = ['FooTest']

$ cat start1.py
from foo import FooTest
x = FooTest()
print "Works!"
sab@pcf2245:~/test$
---------

The test works:

---------
$ python start1.py
Works!
$
---------

However, if the module is imported elsewhere, e.g. in the following
directory structure:

---------
test
|-- Obj.py
|-- __init__.py
|-- foo
| |-- FooTest.py
| `-- __init__.py
`-- start1.py
test2
`-- start2.py
---------

Where start2.py has the following content:

---------
$ cd test2
$ cat start2.py
import sys, os.path
sys.path.insert(0,
os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
import test
import test.foo
print 'Works!'
---------

It does not work:

---------
$ python start2.py
Traceback (most recent call last):
File "start2.py", line 4, in <module>
import test.foo
File "/home/sab/test/foo/__init__.py", line 1, in <module>
from FooTest import FooTest
File "/home/sab/test/foo/FooTest.py", line 1, in <module>
from Obj import Obj
ImportError: No module named Obj
 
G

Gabriel Genellina

Given the following directory structure:

---------
|-- Obj.py
|-- __init__.py
|-- foo
| |-- FooTest.py
| `-- __init__.py
`-- start1.py
---------

The container looks like a package (you didn't tell us the name).
Should be placed somewhere accessible thru sys.path
start1.py does NOT belong to the package, neither start2.py; place
them somewhere else. They should import the package as any other
client code, without doing any import tricks nor playing with
sys.path.
 
S

Samuel

The container looks like a package (you didn't tell us the name).
Should be placed somewhere accessible thru sys.path

But it is. I added the path to sys.path.
They should import the package as any other
client code, without doing any import tricks nor playing with
sys.path.

Why does it matter whether I install it in sys.path or whether
sys.path is modified? What's the difference?

What I am doing is I ship two modules in one tarball with my software.
The software is only unpacked and ran. It has to work without
installation.

-Samuel
 
S

Samuel

Why does it matter whether I install it in sys.path or whether
sys.path is modified? What's the difference?

What I am doing is I ship two modules in one tarball with my software.
The software is only unpacked and ran. It has to work without
installation.

I see now how this works; when a script is ran, only the top-level of
the current module is searched. Now that's just ugly, but well... at
least I now know how to work around this.

Thanks,
-Samuel
 
G

Gabriel Genellina

Why does it matter whether I install it in sys.path or whether
sys.path is modified? What's the difference?

Because it's more simple, less error prone, easier to test, more
efficient...
What I am doing is I ship two modules in one tarball with my software.
The software is only unpacked and ran. It has to work without
installation.

That's fine, and a good requirement. Place start2.py inside the
container directory, and your package beneath it. Then you don't have
to modify sys.path to find the package - "import packagename" just
works. And it still works if the user installs the package (into site-
packages, by example).

start1.py
start2.py
packagename/
|-- Obj.py
|-- __init__.py
|-- foo/
|-- FooTest.py
`-- __init__.py

Packages are... well, packages, boxes. Don't try to import a module
inside a package as it were a standalone module - relative imports
won't work then.
This was discussed some time ago <http://groups.google.com.ar/group/
comp.lang.python/msg/b2d0c36e388e9ab6>
 
S

Samuel

Because it's more simple, less error prone, easier to test, more
efficient...


That's fine, and a good requirement. Place start2.py inside the
container directory, and your package beneath it. Then you don't have
to modify sys.path to find the package - "import packagename" just
works. And it still works if the user installs the package (into site-
packages, by example).

start1.py
start2.py
packagename/
|-- Obj.py
|-- __init__.py
|-- foo/
|-- FooTest.py
`-- __init__.py

Packages are... well, packages, boxes. Don't try to import a module
inside a package as it were a standalone module

But the start2.py script *is* part of the library. It should be in the
package.
However, I just found that Python 2.5 introduces relative imports.
This sounds like an attempt to remedy the situation.

-Samuel
 
G

Gabriel Genellina

But the start2.py script *is* part of the library. It should be in the
package.

If it imports the package, it cannot be part of the package itself.
However, I just found that Python 2.5 introduces relative imports.
This sounds like an attempt to remedy the situation.

For relative imports to work, the importing module must know that it is
part of a package. That is not the case if you run a script located inside
the package.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top