Reputation: 7146
I was looking at some code with two __import__
statements, and the second __import__
statement doesn't work unless the first one has already been run.
The directory structure is like this:
dir1
|-__init__.py
|-subdir1
| |-__init__.py
| |-file1.py
| |-file2.py
|
|-subdir2
|-__init__.py
|-file1.py
|-file2.py
The code has two __import__
statements:
m = __import__('dir1.'+subdir1, fromlist=[file1])
...
m = __import__(file2, fromlist=[class_inside_file2])
The first one makes sense - it is roughly the equivalent of doing
from dir1.subdir1 import file1
but allows for the subdirectory and file to be provided dynamically. It is the second statement that I don't understand why it works. It looks like it should be the equivalent of
from file2 import class_inside_file2
This shouldn't work as file2.py
is in subdir1
, but my current working directory is two levels above that. Additionally, all of the __init__.py
files are empty.
As you would expect, the second import statement fails with an ImportError
if it is run by itself. However, after the first import statement has run the second one works. Why?
Upvotes: 8
Views: 244
Reputation: 19554
It is not just the __import__ statements as I can't replicate this behavior.
$ mkdir -p dir1/subdir1 dir1/subdir2
$ touch dir1/__init__.py dir1/subdir1/__init__.py dir1/subdir2/__init__.py
$ echo "print '1.1'" > dir1/subdir1/file1.py
$ echo "print '1.2'" > dir1/subdir1/file2.py
$ echo "print '2.2'" > dir1/subdir2/file2.py
$ echo "print '2.1'" > dir1/subdir2/file1.py
Gives the following structure:
$ find . -name "*.py"
./dir1/__init__.py
./dir1/subdir1/__init__.py
./dir1/subdir1/file1.py
./dir1/subdir1/file2.py
./dir1/subdir2/__init__.py
./dir1/subdir2/file1.py
./dir1/subdir2/file2.py
However the 2nd __import__ command you've posted fails as expected:
$ python
Python 2.7.6 (default, Nov 18 2013, 11:23:24)
[GCC 4.2.1 Compatible Apple LLVM 4.2 (clang-425.0.24)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> subdir1 = 'subdir1'
>>> file1 = 'file1'
>>> m = __import__('dir1.'+subdir1, fromlist=[file1])
1.1
>>> file2 = 'file2'
>>> class_inside_file2 = '*'
>>> m = __import__(file2, fromlist=[class_inside_file2])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named file2
Upvotes: 4
Reputation: 7146
It turns out the explanation is rather dumb. file1
modifies sys.path
to add subdir1
to the path. With subdir1
on the path, it can obviously find file2
directly without having specify any packages.
Moral of the story - side effects (like things happening when you import a module) are dumb because it can frequently cause issues that seem bizarre and can be hard to diagnose.
Upvotes: 5