Учет меняющегося пути

1

В отношении другого вопроса, как вы определяете пути, которые могут измениться? Например, если программа вызывает файл в том же каталоге, что и программа, вы можете просто использовать путь ".\Foo.py" в * nix. Однако, по-видимому, Windows любит, чтобы путь был жестко закодирован, например. "C:\Python_project\foo.py".

Что произойдет, если путь изменится? Например, файл может быть не на диске C:, а на флэш-накопителе или внешнем диске, который может изменить букву диска. Файл все равно может находиться в том же каталоге, что и программа, но он не будет соответствовать букве диска в коде.

Я хочу, чтобы программа была кросс-платформенной, но я ожидаю, что мне, возможно, придется использовать os.name или что-то, чтобы определить, какой блок кода пути использовать.

Теги:
file
path

4 ответа

4
Лучший ответ

Простой ответ: вы определяете абсолютный путь на основе среды.

Что вам действительно нужно, это несколько указателей. Существуют различные биты информации о времени выполнения и среде, которые вы можете собирать из разных мест в стандартной библиотеке (и они, безусловно, помогают мне, когда я хочу развернуть приложение на окнах).

Итак, сначала некоторые общие вещи:

  • 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 является примером этого.

Если вы всегда проходите путь абсолютно, вы никогда не столкнетесь с проблемами рабочих каталогов.

0

Что конкретно - вы имеете в виду под "вызовом файла... 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.

0

Если ваш файл всегда находится в том же каталоге, что и ваша программа, выполните следующие действия:

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.

-1

Я понял, используя 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

Кажется, что он работает. Спасибо за идеи.

  • 0
    Ммм ... Это не обязательно. Используйте os.path.join. Он уже знает "/" против "\" для вашей конкретной ОС.
  • 0
    Конечно, понизить меня, потому что я все еще учусь. Я не знал о os.path.join; Я просто счастлив, что получил что-то, что работает. Иногда я очень устаю от этого сайта.
Показать ещё 8 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню