Где Python ищет файлы в скрипте?

Итак, я только что написал этот класс для титульного экрана, и он хорошо работает. Однако один из людей, с которыми я работаю над проектом, сказал, что мне не следует использовать:

os.chdir(os.getcwd() + "/..")

resource = (os.getcwd() + "/media/file name")

чтобы попасть в супер каталог. Однако он кое-что упомянул о pythonpath. Мы используем Eclipse, если это может помочь.

Для большего контекста мы создаем многоплатформенную игру, поэтому мы не можем просто синхронизировать наши каталоги и жестко запрограммировать ее (хотя мы используем git, чтобы синхронизировать рабочий каталог). По сути, мне нужен какой-то способ перейти из файла сценария в папке «src» в папку «media», которая находится рядом с ним (AKA Там есть папка super (проект) с папками «src» и «media» в ней) .

Любая помощь будет принята с благодарностью, но, пожалуйста, не говорите «погуглите», потому что я пробовал это, прежде чем приехать сюда (не знаю, часто ли это здесь, но я видел это слишком много раз в другом месте ... когда я искал ответы в Google, извините, если я говорю это как отрывисто)


person ElectricErger    schedule 05.03.2013    source источник
comment
Я этого не вижу. Я вижу, насколько похоже мое текущее решение, но это только проблема. Есть способ сделать это, это лучше, чем то, как я это делаю.   -  person ElectricErger    schedule 05.03.2013
comment
Я думаю, что вопрос не столько в том, чтобы попасть в родительский каталог, сколько в том, чтобы перейти в каталог относительно скрипта / программы, как указывает название. Итак, я думаю, что этот вопрос не дублирует stackoverflow.com/q/2860153/42973.   -  person Eric O Lebigot    schedule 05.03.2013


Ответы (3)


Программы Python действительно имеют концепцию текущего рабочего каталога, который обычно является каталогом, из которого был запущен сценарий. Это «место, где они ищут файлы» с относительным путем.

Однако, поскольку вашу программу можно запустить из папки, отличной от той, в которой она находится, ваш справочный каталог должен вместо этого ссылаться на каталог, в котором находится ваш скрипт ( текущий каталог не связан с расположением вашего скрипта, как правило). Каталог, в котором находится ваш скрипт, получается с помощью

script_dir = os.path.dirname(__file__)

Обратите внимание, что этот путь может быть относительным (возможно, пустым), поэтому по-прежнему важно, чтобы текущий рабочий каталог вашего скрипта совпадал с каталогом, когда ваш скрипт читался интерпретатором python (когда установлено __file__). Важно преобразовать возможно относительный script_dir в абсолютный путь, если текущий рабочий каталог будет изменен позже в коде:

# If script_dir is relative, the current working directory is used, here. This is correct if the current
# working directory is the same as when the script was read by the Python interpreter (which is
# when __file__ was set):
script_dir = os.path.abspath(script_dir)

Затем вы можете перейти в каталог media в родительском каталоге с помощью независимого от платформы

os.path.join(script_dir, os.path.pardir, 'media')

Фактически os.path.pardir (или эквивалентно os.pardir) - это соглашение о родительских каталогах, не зависящее от платформы, а os.path.join() просто объединяет пути независимым от платформы способом.

person Eric O Lebigot    schedule 05.03.2013
comment
+1 за использование __file__ и решение abspath-проблемы - person Thorsten Kranz; 05.03.2013

Я бы порекомендовал что-то вроде:

import os.path

base_folder = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
media_folder = os.path.join(base_folder, "media")
src_folder = os.path.join(base_folder, "src")

resource = os.path.join(media_folder, "filename")

for path in [base_folder, media_folder, src_folder, resource]:
    print path

Основные ингредиенты:

  • __file__: получает путь к текущему исходному файлу (в отличие от sys.argv[0], который дает путь к сценарию, который был вызван)
  • os.path.split(): разделяет путь на относительное имя файла / папки и содержащую его базовую папку. Использование его дважды, как в base_folder = ..., даст родительский каталог.
  • os.path.join: Независимая от ОС и правильная комбинация имен путей. Известно об отсутствии или нескольких / или \
person Thorsten Kranz    schedule 05.03.2013
comment
-1, потому что это зависит от того, как вызывается файл python. os.path.split(__file__)[0] в некоторых случаях может быть пустым, что приводит к поломке. Также есть встроенные способы сделать это (а именно os.path.dirname), поэтому лучше использовать их, чем возиться с split - person wim; 05.03.2013
comment
dirname это то, что я, конечно же, хотел использовать. Фиксированный ответ, чтобы отразить это. Основным моментом моего ответа является использование __file__, о котором не упоминалось в предыдущем ответе. - person Thorsten Kranz; 05.03.2013
comment
+1, потому что вы правы: __file__ - лучший справочный каталог, поскольку папка media размещается относительно сценария, а не относительно того, где его запускают пользователи (т.е. текущий каталог действительно не так актуален). - person Eric O Lebigot; 05.03.2013

Рассмотрите возможность использования os.path.dirname() и os.path.join(). Они должны работать независимо от платформы.

person Jim Garrison    schedule 05.03.2013
comment
Разве мне не нужен путь для so.path.dirname (), и разве эта платформа не зависит? - person ElectricErger; 05.03.2013
comment
Да, это так - используйте os.path.dirname(os.path.abspath(__file__)) - person wim; 05.03.2013
comment
@JimGarrison: это не сработает, если сценарий не запускается из каталога, в котором он находится. Вероятно, это одна из причин, по которой некоторые люди упомянули, что код в вопросе не следует использовать (не говоря уже о том, что некоторые другие части кода могут изменить текущий рабочий каталог). - person Eric O Lebigot; 05.03.2013