В отношении другого вопроса, как вы определяете пути, которые могут измениться? Например, если программа вызывает файл в том же каталоге, что и программа, вы можете просто использовать путь ".\Foo.py" в * nix. Однако, по-видимому, Windows любит, чтобы путь был жестко закодирован, например. "C:\Python_project\foo.py".
Что произойдет, если путь изменится? Например, файл может быть не на диске C:, а на флэш-накопителе или внешнем диске, который может изменить букву диска. Файл все равно может находиться в том же каталоге, что и программа, но он не будет соответствовать букве диска в коде.
Я хочу, чтобы программа была кросс-платформенной, но я ожидаю, что мне, возможно, придется использовать os.name или что-то, чтобы определить, какой блок кода пути использовать.
Простой ответ: вы определяете абсолютный путь на основе среды.
Что вам действительно нужно, это несколько указателей. Существуют различные биты информации о времени выполнения и среде, которые вы можете собирать из разных мест в стандартной библиотеке (и они, безусловно, помогают мне, когда я хочу развернуть приложение на окнах).
Итак, сначала некоторые общие вещи:
os.path
- стандартный библиотечный модуль с множеством кросс-платформенных манипуляций. Твой лучший друг. "Следуйте за os.path", который я когда-то читал в книге.__file__
- Местоположение текущего модуля.sys.executable
- Местоположение запущенного Python.Теперь вы можете довольно много подбирать все, что захотите, из этих трех источников. Функции из os.path помогут вам обойти дерево:
os.path.join('path1', 'path2')
- объединить сегменты маршрута кросс-платформенным способом.os.path.expanduser('a_path')
- найдите путь a_path
в домашнем каталоге пользователяos.path.abspath('a_path')
- преобразовать относительный путь к абсолютному путиos.path.dirname('a_path')
- получить каталог, в котором находится путьИтак, комбинируя это, например:
# script1.py
# Get the path to the script2.py in the same directory
import os
this_script_path = os.path.abspath(__file__)
this_dir_path = os.path.dirname(this_script_path)
script2_path = os.path.join(this_dir_path, 'script2.py')
print script2_path
И запустив его:
ali@work:~/tmp$ python script1.py
/home/ali/tmp/script2.py
Теперь для вашего конкретного случая кажется, что вы немного запутались в концепции "рабочего каталога" и "каталога, в котором находится script". Они могут быть одинаковыми, но они также могут быть разными. Например, "рабочий каталог" можно изменить, и поэтому функции, которые его используют, могут найти то, что они ищут иногда, но не другие. subprocess.Popen
является примером этого.
Если вы всегда проходите путь абсолютно, вы никогда не столкнетесь с проблемами рабочих каталогов.
Что конкретно - вы имеете в виду под "вызовом файла... foo.py"?
Импорт? Если это так, путь полностью за пределами вашей программы. Установите переменную среды PYTHONPATH
с помощью .
или c:\
или на уровне оболочки. Например, вы можете написать сценарии с двумя строками оболочки, чтобы установить переменную окружения и запустить Python.
Окна
SET PYTHONPATH=C:\path\to\library
python myapp.py
Linux
export PYTHONPATH=./relative/path
python myapp.py
ExecFile? Рассмотрите возможность использования импорта.
Чтение и Eval? Рассмотрите возможность использования импорта.
Если PYTHONPATH слишком сложный, тогда поместите свой модуль в каталог Python lib/site-packages, где он по умолчанию будет помещен в PYTHONPATH.
Если ваш файл всегда находится в том же каталоге, что и ваша программа, выполните следующие действия:
def _isInProductionMode():
""" returns True when running the exe,
False when running from a script, ie development mode.
"""
return (hasattr(sys, "frozen") or # new py2exe
hasattr(sys, "importers") # old py2exe
or imp.is_frozen("__main__")) #tools/freeze
def _getAppDir():
""" returns the directory name of the script or the directory
name of the exe
"""
if _isInProductionMode():
return os.path.dirname(sys.executable)
return os.path.dirname(__file__)
должен работать. Кроме того, я использовал py2exe для своего собственного приложения и не тестировал его с другими приложениями конверсии exe.
Я понял, используя os.getcwd(). Я также узнал об использовании os.path.join, чтобы автоматически определить правильный формат пути на основе ОС. Здесь код:
def openNewRecord(self, event): # wxGlade: CharSheet.<event_handler>
"""Create a new, blank record sheet."""
path = os.getcwd()
subprocess.Popen(os.path.join(path, "TW2K_char_rec_sheet.py"), shell=True).stdout
Кажется, что он работает. Спасибо за идеи.