Issue13912
Created on 2012-01-30 17:00 by jason.coombs, last changed 2012-11-10 16:44 by jason.coombs. This issue is now closed.
| Messages (12) | |||
|---|---|---|---|
| msg152331 - (view) | Author: Jason R. Coombs (jason.coombs) * ![]() |
Date: 2012-01-30 17:00 | |
The Python 2.7.2 docs say this about __import__:
Positive values for level indicate the number of parent directories to search relative to the directory of the module calling __import__().
But I find that even when setting level=1, the parent directory is not searched.
I've created this project tree to replicate the issue:
jaraco@devjaraco:~$ tree master
master
├── __init__.py
├── pkgA
│ ├── foo.py
│ └── __init__.py
└── pkgB
├── bar.py
└── __init.py
2 directories, 5 files
jaraco@devjaraco:~$ cat master/pkgA/foo.py
bar = __import__('pkgB', level=1).bar
jaraco@devjaraco:~$ cat master/pkgB/bar.py
var = "success"
It fails as so with python 2.7.2:
jaraco@devjaraco:~$ python2.7 -c "import master.pkgA.foo"
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "master/pkgA/foo.py", line 2, in <module>
bar = __import__('pkgB', level=1).bar
ImportError: No module named pkgB
It's conceivable I'm not using this correctly, but if so, I'm unable to find my mistake. I've confirmed that foo.__name__ is 'master.pkgA.foo'. I've tried using level=2 (in case I was off by one, but that wasn't the case).
|
|||
| msg152336 - (view) | Author: Eric Snow (eric.snow) * ![]() |
Date: 2012-01-30 17:35 | |
what value do you see for __package__ in pkgA? |
|||
| msg152341 - (view) | Author: Brett Cannon (brett.cannon) * ![]() |
Date: 2012-01-30 18:05 | |
You have a typo in a filename: it should be pkgB/__init__.py (not the missing trailing underscores). |
|||
| msg152342 - (view) | Author: Jason R. Coombs (jason.coombs) * ![]() |
Date: 2012-01-30 19:31 | |
Sorry for the mistake.
I corrected the pkgB package, but the result is the same:
jaraco@devjaraco:~$ tree master
master
├── __init__.py
├── __init__.pyc
├── pkgA
│ ├── foo.py
│ ├── foo.pyc
│ ├── __init__.py
│ └── __init__.pyc
└── pkgB
├── bar.py
└── __init__.py
2 directories, 8 files
jaraco@devjaraco:~$ python2.7 -c 'import master.pkgA; print("pkgA.__package__ is {}".format(master.pkgA.__package__)); import master.pkgA.foo'
pkgA.__package__ is None
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "master/pkgA/foo.py", line 2, in <module>
bar = __import__('pkgB', level=1).bar
ImportError: No module named pkgB
As you can see, __package__ for pkgA is None. Same is true for master.__package__.
|
|||
| msg152354 - (view) | Author: Brett Cannon (brett.cannon) * ![]() |
Date: 2012-01-30 22:42 | |
I see your mistake now: you need to call it as __import__('pkgB', globals(), index=1), else __import__ has no clue how to anchor your import in the relative package space.
Try that and let me know if it makes it work.
And why exactly are you trying to call __import__ directly? You should be using importlib.import_module() for programmatic imports.
|
|||
| msg152357 - (view) | Author: Jason R. Coombs (jason.coombs) * ![]() |
Date: 2012-01-30 23:05 | |
Thanks for the tip Brent. Still, no luck.
jaraco@devjaraco:~$ python2.7 -c 'import master.pkgA; print("pkgA.__package__ is {}".format(master.pkgA.__package__)); import master.pkgA.foo'
pkgA.__package__ is None
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "master/pkgA/foo.py", line 2, in <module>
bar = __import__('pkgB', globals(), level=1).bar
ImportError: No module named pkgB
I considered importlib, but it is only included for Python 2.7+ and I have to support Python 2.6. I'm using programmatic imports for a few reasons:
1) I'm importing the modules for the side effects, so I don't need or want the name in the namespace.
2) If I import it naturally, I get pyflakes warnings that it's an used imports.
3) The order of imports is important. If I place it too early in the imports, it doesn't have the state it needs and fails.
4) By placing it in the top of the file with other imports, it's not obvious why it's being imported, so requires comments.
5) The most appropriate place to invoke this functionality is in a specific function, "run_app".
I see now that there is an importlib backport in the cheeseshop for earlier versions of Python. Given your recommendation, I'll give that a try.
|
|||
| msg152361 - (view) | Author: Eric Snow (eric.snow) * ![]() |
Date: 2012-01-30 23:33 | |
Jason: just a warning. importlib_backport is a relatively naive tool for generating the backport from the py3k source. It's also relatively fragile and at this point probably doesn't work with the default branch. |
|||
| msg152365 - (view) | Author: Eric Snow (eric.snow) * ![]() |
Date: 2012-01-31 01:46 | |
The problem is your level is off and the name is incomplete. master.pkgA.foo.py should have the following:
__import__('pkgB.bar', master.pkgA.__dict__, level=2).bar
or
__import__('pkgB.bar', master.pkgA.__dict__, fromlist=['-'], level=2)
|
|||
| msg152375 - (view) | Author: Nick Coghlan (ncoghlan) * ![]() |
Date: 2012-01-31 12:02 | |
It sounds like you may want runpy.run_module [1], rather than using imports at all. If you know how many levels up you want to go, it isn't hard to do your own munging of __name__ to create absolute module references to pass to runpy. The signature of __import__ is known to be unintuitive to the point of being insane - it's really designed for the convenience of the compiler and the interpreter, not for direct use by humans. [1] http://docs.python.org/release/2.6.7/library/runpy#runpy.run_module |
|||
| msg152391 - (view) | Author: Brett Cannon (brett.cannon) * ![]() |
Date: 2012-01-31 16:01 | |
On Mon, Jan 30, 2012 at 18:33, Eric Snow <report@bugs.python.org> wrote: > > Eric Snow <ericsnowcurrently@gmail.com> added the comment: > > Jason: just a warning. importlib_backport is a relatively naive tool for > generating the backport from the py3k source. It's also relatively fragile > and at this point probably doesn't work with the default branch. > I think Jason was thinking of http://pypi.python.org/pypi/importlib/ which is my personal backport of importlib from Python 2.7 all the way back to Python 2.3. |
|||
| msg175263 - (view) | Author: Eric Snow (eric.snow) * ![]() |
Date: 2012-11-10 05:42 | |
Are you okay on this, Jason? |
|||
| msg175288 - (view) | Author: Jason R. Coombs (jason.coombs) * ![]() |
Date: 2012-11-10 16:44 | |
Yes. Since Nick's comment , I've been using importlib for all programmatic imports with great success. |
|||
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2012-11-10 16:44:45 | jason.coombs | set | status: pending -> closed resolution: invalid messages: + msg175288 |
| 2012-11-10 05:42:56 | eric.snow | set | status: open -> pending messages: + msg175263 |
| 2012-01-31 16:01:04 | brett.cannon | set | messages: + msg152391 |
| 2012-01-31 12:02:07 | ncoghlan | set | nosy:
+ ncoghlan messages: + msg152375 |
| 2012-01-31 01:46:53 | eric.snow | set | messages: + msg152365 |
| 2012-01-30 23:33:30 | eric.snow | set | messages: + msg152361 |
| 2012-01-30 23:05:30 | jason.coombs | set | messages: + msg152357 |
| 2012-01-30 22:42:25 | brett.cannon | set | messages: + msg152354 |
| 2012-01-30 19:31:05 | jason.coombs | set | status: closed -> open resolution: invalid -> (no value) messages: + msg152342 |
| 2012-01-30 18:05:06 | brett.cannon | set | status: open -> closed nosy: + brett.cannon messages: + msg152341 resolution: invalid |
| 2012-01-30 17:35:25 | eric.snow | set | nosy:
+ eric.snow messages: + msg152336 |
| 2012-01-30 17:00:47 | jason.coombs | create | |
