Различное поведение импорта в идентичном коде в интерактивном и неинтерактивном режимах - почему путь поиска модуля отличается? - PullRequest
1 голос
/ 28 октября 2019

Этот вопрос относится к Невозможно импортировать модуль с importlib.import_module , который, я не думаю, вообще дошел до корня проблемы.

Я пытаюсьчтобы понять причину различий с importlib, используемым в интерактивном интерпретаторе, и неинтерактивным сценарием, потому что с каждым я получаю разные результаты.

У меня есть папка, содержащая myscript.py, и яхотите импортировать модуль с именем module из подпапки, my_subdir исходного рабочего каталога. Я хочу сделать это, перейдя в этот каталог и работая там. Я знаю, что есть другие решения для доступа к модулю в подкаталоге, но об этом я бы хотел поговорить.

Ниже приведено содержимое myscript.py, которое просто перемещается вподкаталог и пытается импортировать модуль оттуда, а затем вызвать некоторую функцию hello-world из модуля:

#!/home/chris/anaconda2/bin/python
import sys
import platform
import os
import importlib

print("Python version "+ platform.python_version())
print(sys.path)

os.chdir('my_subdir')
my_module = importlib.import_module('module')
my_module.my_function()

Когда я запускаю это из командной строки, Python не может найти модуль. Кажется, что система импорта не знает об изменении каталога с os.chdir():

(base) chris@linux-om3m:~/workspace> python myscript.py 
Python version 2.7.15
['/home/chris/workspace', '/home/chris/anaconda2/lib/python27.zip', '/home/chris/anaconda2/lib/python2.7', '/home/chris/anaconda2/lib/python2.7/plat-linux2', '/home/chris/anaconda2/lib/python2.7/lib-tk', '/home/chris/anaconda2/lib/python2.7/lib-old', '/home/chris/anaconda2/lib/python2.7/lib-dynload', '/home/chris/anaconda2/lib/python2.7/site-packages', '/home/chris/anaconda2/lib/python2.7/site-packages']
Traceback (most recent call last):
  File "myscript.py", line 11, in <module>
    my_module = importlib.import_module('module')
  File "/home/chris/anaconda2/lib/python2.7/importlib/__init__.py", line 37, in import_module
    __import__(name)
ImportError: No module named module

Однако, когда я набираю тот же сценарий в интерактивном интерпретаторе, он прекрасно работает:

(base) chris@linux-om3m:~/workspace> python
Python 2.7.15 | packaged by conda-forge | (default, Jul  2 2019, 00:39:44) 
[GCC 7.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> import platform
>>> import os
>>> import importlib
>>> print("Python version "+ platform.python_version())
Python version 2.7.15
>>> print(sys.path)
['', '/home/chris/anaconda2/lib/python27.zip', '/home/chris/anaconda2/lib/python2.7', '/home/chris/anaconda2/lib/python2.7/plat-linux2', '/home/chris/anaconda2/lib/python2.7/lib-tk', '/home/chris/anaconda2/lib/python2.7/lib-old', '/home/chris/anaconda2/lib/python2.7/lib-dynload', '/home/chris/anaconda2/lib/python2.7/site-packages', '/home/chris/anaconda2/lib/python2.7/site-packages']
>>> os.chdir('my_subdir')
>>> my_module = importlib.import_module('module')
>>> my_module.my_function()
Here I am!
>>> 

Я могу исправить эту проблему, вручную обновив sys.path на sys.path.append(os.getcwd()) после выполнения os.chdir - но я не понимаю, почему это необходимо только в неинтерактивном режиме.

Единственное, что я замечаю (и напечатано здесь в вставленном выводе), это то, что в интерактивном интерпретаторе sys.path имеет запись с пустой строкой, тогда как в неинтерактивном режиме он содержит рабочий каталог, в котором я вызывал python.

Я знаю, что могу решить эту проблему, используя относительный импорт, и сейчас я решаю проблему, используя sys.path.append(os.getcwd()), но я хотел бы понять, почему существует разница между интерактивным и не-интерактивно.

Я получаю одинаковые результаты с Python 2.7 и Python 3.6.

1 Ответ

1 голос
/ 28 октября 2019

Как вы отметили в своем комментарии, добавление '' к sys.path устраняет проблему. Это потому, что '' представляет ваш cwd, поэтому os.chdir() знает, где правильно найти ваш подкаталог my_subdir (см. Почему первый элемент в sys.path python - пустая строка? ).

Использование абсолютного пути для my_subdir также должно решить вашу проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...