Модуль Python os открывает файл над текущим каталогом с относительным путем

В документации для модуля ОС, похоже, нет информации о том, как открыть файл, который не находится в подкаталоге или текущем каталоге, в котором выполняется скрипт, без полного пути. Моя структура каталогов выглядит так.

/home/matt/project/dir1/cgi-bin/script.py
/home/matt/project/fileIwantToOpen.txt

open("../../fileIwantToOpen.txt","r")

Выдает ошибку, что файл не найден. Но если я запущу интерпретатор Python в каталоге cgi-bin и попробую open("../../fileIwantToOpen.txt","r"), он сработает. Я не хочу жестко кодировать полный путь по очевидным причинам переносимости. Есть ли в модуле ОС набор методов, которые МОГУТ сделать это?


person Matt Phillips    schedule 07.12.2010    source источник
comment
Хм. Это может быть ошибка прав доступа, или рабочий каталог для CGI может не совпадать с вашим интерпретатором Python. Точное сообщение об ошибке может помочь. Кроме того, в CGI попробуйте print os.getcwd() и посмотрите, что там написано.   -  person Jason Orendorff    schedule 08.12.2010
comment
Ваш CGI-скрипт работает в chroot-тюрьме? Если это так, то это не сработает, так как вы не сможете сбежать из тюрьмы.   -  person Adam Rosenfield    schedule 08.12.2010
comment
@ Адам Розенфилд нет. @Jason Я буквально запускаю интерпретатор python в каталоге cgi-bin, поэтому я не понимаю, как он будет работать в нем, а не внутри скрипта, который выполняется в каталоге cgi-bin.   -  person Matt Phillips    schedule 08.12.2010
comment
Вышеупомянутое сработало для меня в сочетании с этим сообщением stackoverflow.com/a/3283336/706798   -  person Anton    schedule 12.06.2013


Ответы (2)


Путь, указанный для open, должен относиться к текущему рабочему каталогу, из которого вы запускаете скрипт. Таким образом, приведенный выше пример будет работать, только если вы запустите его из каталога cgi-bin.

Простым решением было бы сделать ваш путь относительно скрипта. Одно возможное решение.

from os import path

basepath = path.dirname(__file__)
filepath = path.abspath(path.join(basepath, "..", "..", "fileIwantToOpen.txt"))
f = open(filepath, "r")

Таким образом, вы получите путь к скрипту, который вы запускаете (базовый путь), и соедините его с относительным путем к файлу, который хотите открыть. os.path позаботится о деталях соединения двух путей.

person terminus    schedule 07.12.2010
comment
эта команда просто дает мне ../../fileIwantToOpen.txt в качестве пути и все еще не может его найти. - person Matt Phillips; 08.12.2010
comment
@terminus: basepath = os.path.dirname(sys.argv[0]) и os.path.join(basepath, '..', '..', 'fileIwantToOpen.txt'). Я бы тоже использовал __file__, а не sys.argv[0]. - person Chris Morgan; 08.12.2010
comment
@Chris Спасибо, исправлено. Кажется, split моя дурная привычка. - person terminus; 08.12.2010
comment
Я все еще получаю полный путь к текущему каталогу с добавлением ../../fileIwantToOpen.txt в конце. - person Matt Phillips; 08.12.2010
comment
@terminus: также не следует вызывать переменную file (из-за __builtins__.file). И import os, а не import os.path. - person Chris Morgan; 08.12.2010
comment
@Matt: убедитесь, что у вас есть бит os.path.abspath - os.path.join просто присоединится к ним, abspath отсортирует ... Это работает. - person Chris Morgan; 08.12.2010
comment
@Matt, это странно, поскольку os.path.abspath должен преобразовывать относительные пути в абсолютные. - person terminus; 08.12.2010
comment
Да, я почему-то пропустил эту часть. os.path.dirname тоже работал у меня. Теперь это работает! - person Matt Phillips; 08.12.2010

Это должно переместить вас в каталог, где находится скрипт, если вы еще не там:

file_path = os.path.dirname(__file__)
if file_path != "":
    os.chdir(file_path)
open("../../fileIwantToOpen.txt","r")
person Andrew Clark    schedule 07.12.2010