Абсолютный путь файлового объекта
Это обсуждалось ранее в StackOverflow - я пытаюсь найти хороший способ найти абсолютный путь к файловому объекту, но мне нужно, чтобы он был устойчивым до os.chdir()
, поэтому не может использовать
f = file('test')
os.path.abspath(f.name)
Вместо этого мне было интересно, является ли следующее хорошим решением - в основном расширяя класс файла, чтобы при открытии сохранялся абсолютный путь файла:
class File(file):
def __init__(self, filename, *args, **kwargs):
self.abspath = os.path.abspath(filename)
file.__init__(self, filename, *args, **kwargs)
Тогда можно сделать
f = File('test','rb')
os.chdir('some_directory')
f.abspath # absolute path can be accessed like this
Существуют ли какие-либо риски при этом?
Ответы
Ответ 1
Один существенный риск состоит в том, что после открытия файла процесс обрабатывается этим файлом с помощью дескриптора файла, а не его пути. Во многих операционных системах путь к файлу может быть изменен каким-либо другим процессом (операцией mv
в несвязанном процессе, скажем), и файловый дескриптор по-прежнему действителен и относится к тому же файлу.
Я часто пользуюсь этим, например, начиная загрузку большого файла, тогда реализация целевого файла не там, где я хочу, и прыгая в отдельную оболочку и перемещая ее в нужное место - пока загрузка не прерывается.
Таким образом, плохая идея зависит от пути, остающегося тем же самым для жизни процесса, когда нет такой гарантии, предоставляемой операционной системой.
Ответ 2
Это зависит от того, для чего вам это нужно.
Пока вы понимаете ограничения - кто-то может переместить, переименовать или жестко связать файл в промежутке времени - для этого есть много подходящих применений. Вы можете удалить файл, когда закончите с ним, или если что-то пойдет не так во время его написания (например, gcc делает это при записи файлов):
f = File(path, "w+")
try:
...
except:
try:
os.unlink(f.abspath)
except OSError: # nothing we can do if this fails
pass
raise
Если вы просто хотите иметь возможность идентифицировать файл в сообщениях пользователя, то уже есть file.name. Невозможно использовать это (надежно) для чего-либо еще, к сожалению; нет способа различать имя файла "<stdin>
" и sys.stdin, например.
(Вам действительно не нужно выводить из встроенного класса только для добавления в него атрибутов, это просто уродливая непоследовательная причуда Python...)