ImportError depending on the calling module

Discussion in 'Python' started by Samuel, Sep 6, 2007.

  1. Samuel

    Samuel Guest

    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
    ---------

    How would you import the foo module correctly?

    -Samuel
     
    Samuel, Sep 6, 2007
    #1
    1. Advertising

  2. On 6 sep, 08:47, Samuel <> wrote:

    > 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.

    --
    Gabriel Genellina
     
    Gabriel Genellina, Sep 6, 2007
    #2
    1. Advertising

  3. Samuel

    Samuel Guest

    On Sep 6, 5:44 pm, Gabriel Genellina <> wrote:
    > On 6 sep, 08:47, Samuel <> wrote:
    > > 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


    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
     
    Samuel, Sep 6, 2007
    #3
  4. Samuel

    Samuel Guest

    On Sep 6, 6:13 pm, Samuel <> wrote:
    > 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
     
    Samuel, Sep 6, 2007
    #4
  5. On 6 sep, 13:13, Samuel <> wrote:
    > On Sep 6, 5:44 pm, Gabriel Genellina <> wrote:


    > > 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?


    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>

    --
    Gabriel Genellina
     
    Gabriel Genellina, Sep 6, 2007
    #5
  6. Samuel

    Samuel Guest

    On Sep 6, 6:44 pm, Gabriel Genellina <> wrote:
    > On 6 sep, 13:13, Samuel <> wrote:
    >
    > > On Sep 6, 5:44 pm, Gabriel Genellina <> wrote:
    > > > 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?

    >
    > 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


    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
     
    Samuel, Sep 6, 2007
    #6
  7. En Thu, 06 Sep 2007 14:41:42 -0300, Samuel <> escribi�:
    > On Sep 6, 6:44 pm, Gabriel Genellina <> wrote:
    >> On 6 sep, 13:13, Samuel <> wrote:
    >>
    >> 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.


    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.

    --
    Gabriel Genellina
     
    Gabriel Genellina, Sep 6, 2007
    #7
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. eric_bellard
    Replies:
    1
    Views:
    5,166
    CarlosRivera
    Oct 7, 2004
  2. param
    Replies:
    3
    Views:
    359
    Ivan Vecerina
    Feb 23, 2006
  3. Fabrice
    Replies:
    12
    Views:
    562
    Keith Thompson
    Nov 1, 2007
  4. Eric Brunel
    Replies:
    1
    Views:
    508
    Graham Dumpleton
    Nov 21, 2008
  5. Replies:
    6
    Views:
    273
    Rainer Weikusat
    Nov 8, 2013
Loading...

Share This Page