Абсолютный путь файлового объекта

Это обсуждалось ранее в 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...)