Если запустить сценарий Python, введя в команду, например, python dir1\dir2\file.py, — текущим рабочим каталогом будет каталог, в котором вы находились при вводе этой команды, но не dirl\dir2. С другой стороны, Python автоматически добавляет путь к каталогу, где находится сценарий, в начало пути поиска модулей, поэтому file.py всегда сможет импортировать другие файлы из dirl\dir2, откуда бы он ни был запущен. Чтобы проиллюстрировать это, напишем простой сценарий, выводящий имя текущего рабочего каталога и путь поиска модулей:
C:\…\PP4E\System> type whereami.py import os, sys print(‘my os.getcwd =>’, os.getcwd()) # вывод текущего рабочего каталога print(‘my sys.path =>’, sys.path[:6]) # вывод первых 6 каталогов в пути поиска input() # ожидает нажатия клавиши
Теперь при запуске этого сценария в том каталоге, где он находится, будет выбран ожидаемый текущий рабочий каталог, и имя этого каталога будет добавлено в начало пути поиска. Мы уже встречались со списком sys.path, содержащим путь поиска модулей, — первый его элемент может быть пустой строкой, обозначающей текущий рабочий каталог при работе в интерактивной оболочке; здесь большая часть пути к текущему рабочему каталогу усекается до «…» при отображении:
C:\…\PP4E\System> set PYTHONPATH=C:\PP4thEd\Examples
C:\…\PP4E\System> python whereami.py
my os.getcwd => C:\…\PP4E\System
my sys.path => [‘C:\\…\\PP4E\\System’, ‘C:\\PP4thEd\\Examples’, …другие элементы…]
Если запускать этот сценарий из других каталогов, вслед за нашим перемещением переместится и текущий рабочий каталог (это каталог, в котором вводятся команды), а Python будет добавлять в начало пути поиска модулей каталог, где находится сам сценарий, что позволит сценарию по-прежнему видеть файлы в своем исходном каталоге. Например, если запустить сценарий, поднявшись на один уровень (..), каталог System будет добавлен в начало списка sys.path и станет первым каталогом, в котором Python станет искать модули, импортируемые сценарием whereami.py: первый элемент списка будет нацеливать импорт обратно на каталог, содержащий выполняемый сценарий. Однако поиск файлов, имена которых не содержат полного пути, будет выполняться относительно текущего рабочего каталога (C:\PP4thEd\Examples\ PP4E), а не в его подкаталоге System:
C:\…\PP4E\System> cd ..
C:\…\PP4E> python System\whereami.py
my os.getcwd => C:\…\PP4E
my sys.path => [‘C:\\…\\PP4E\\System’, ‘C:\\PP4thEd\\Examples’, …другие элементы…]
C:\…\PP4E> cd System\temp
C:\…\PP4E\System\temp> python ..\whereami.py
my os.getcwd => C:\…\PP4E\System\temp
my sys.path => [‘C:\\…\\PP4E\\System’, ‘C:\\PP4thEd\\Examples’, …]
В результате поиск файлов, имена которых в сценарии не содержат полных путей, будет выполняться в том месте, где была введена команда (os.getcwd), но операции импортирования по-прежнему будут иметь доступ к каталогу, где находится выполняемый сценарий (через первый элемент в списке sys.path). Наконец, если файл запускается щелчком на ярлыке, текущим рабочим каталогом станет каталог, содержащий файл, на котором выполнен щелчок. Например, следующие строки будут выведены в новом окне консоли DOS при двойном щелчке на whereami.py в проводнике Windows:
my os.getcwd => C:\…\PP4E\System
my sys.path => [‘C:\\…\\PP4E\\System’, …more… ]
В данном случае текущий рабочий каталог, используемый для поиска файлов, и первый каталог в пути поиска модулей совпадают с каталогом, содержащим файл сценария. Обычно все действует так, как предполагается, но здесь вас могут подстерегать две опасности:
• Имена файлов должны содержать полные пути к каталогам, если заранее не известно, из какого каталога будет запущен сценарий.
• Сценарии командной строки не всегда могут использовать текущий рабочий каталог, чтобы увидеть импортируемые файлы, не находящиеся в собственных каталогах сценариев, — для доступа к модулям из других каталогов следует использовать переменную окружения PYTHONPATH и пути к импортируемым пакетам.
Например, сценарии из этой книги всегда могут импортировать другие файлы из собственного исходного каталога, не указывая путь к импортируемому пакету (import file here), независимо от того, как они запущены. Но, чтобы отыскать файлы в другом месте в дереве каталогов примеров, путь поиска должен проходить через корень пакета РР4Е (from PP4E.dir1.dir2 import filethere), даже если запускать сценарии из каталога, содержащего нужный внешний модуль. Как обычно, чтобы обеспечить возможность импортирования модулей, имя каталога PP4E\dirl\dir2 можно также добавить в PYTHONPATH, чтобы сделать file— there видимым отовсюду, без указания пути к импортируемому пакету (хотя лишние каталоги в PYTHONPATH увеличивают вероятность конфликта имен). В любом случае импорт всегда осуществляется из исходного каталога сценария или из другого каталога, находящегося в пути поиска Python, а не из текущего рабочего каталога.
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011