with NamedTemporaryFile(suffix='.shp').name as tmp_shp:
df.to_file(tmp_shp)
В приведенном выше коде я получаю эту ошибку:
AttributeError: __enter__
Как я могу использовать именованный временный файл с помощью оператора with? и поскольку tmp_shp - это всего лишь путь, остается ли он доступным вне with?






Вы используете атрибут name в качестве диспетчера контекста. Пытаться:
with NamedTemporaryFile(suffix='.shp') as tmp_shp:
df.to_file(tmp_shp)
Вы должны использовать оператор with для самого NamedTemporaryFile, но не для его атрибута name.
with NamedTemporaryFile(suffix='.shp') as tmp_file:
df.to_file(tmp_file) # As temp_file is a file object, I think to_file should work?
И как официальный документ, tmp_file будет удален вне with, если вы не передадите delete=False в NamedTemporaryFile.
Это означает, что вам следует with NamedTemporaryFile(suffix='.shp', delete=False) as tmp_file:
Атрибут name - это строка; попытка получить к нему доступ в операторе with делает его управляемым ресурсом (а str не имеет концепции управления контекстом). Вам необходимо управлять самим NamedTemporaryFile и обращаться к name по мере необходимости:
with NamedTemporaryFile(suffix='.shp') as tmp_shp:
df.to_file(tmp_shp.name) # Access .name here, assuming you need a str
Если to_file принимает файловые объекты (я не могу найти документацию для такого метода), вы вообще избегаете использования .name (в любой строке).
Обновлять: Поскольку вы работаете в Windows, вы не можете открыть файл, открытый NamedTemporaryFile, с помощью delete=True (по умолчанию), пока NamedTemporaryFile не будет закрыт (что означает, что вы не можете использовать какие-либо данные, записанные в этот дескриптор файла, поскольку он удален, и вводит состояние гонки, даже если вы используете его исключительно для генерации уникального имени; файл удаляется в в этот момент, так что вы на самом деле просто создаете новый файл, но кто-то другой может подтолкнуть вас к созданию этого файла позже). Лучшее, что я могу предложить здесь, - это использовать его без поддержки удаления, чтобы получить уникальное имя, обернув его для принудительного удаления самостоятельно, например:
tmp_shp = None
try:
with NamedTemporaryFile(suffix='.shp', delete=False) as tmp_shp:
df.to_file(tmp_shp.name) # Access .name here, assuming you need a str
... do any other stuff with the file ...
finally:
if tmp_shp is not None:
os.remove(tmp_shp.name)
Ага, это некрасиво. Здесь не так много хороших вариантов; NamedTemporaryFile принципиально не работает в Windows.
спасибо @ShadowRanger. Я получаю эту ошибку *** RuntimeError: Failed to open C:\Users\rk\AppData\Local\Temp\tmpz5c2fvlg.shp
@ user308827: Ох, у вас Windows. Есть ... вопросы ... с NamedTemporaryFile в Windows. Краткая версия: вы не можете открыть его с помощью большинства программ, если вы не передадите delete=False при его создании (что удаляет большую часть точки), или вы используете его исключительно для создания уникального имени (и закройте его, прежде чем кто-либо другой использует Это).
@ShadowRanger: Вы неправильно поняли (или, по крайней мере, исказили) тему проблемы. Проблема заключается в том, что вы не можете снова открыть файла, лежащего в основе NamedTemporaryFile, по имени, пока файл не будет закрыт, и для повторного открытия требуется delete=False, чтобы предотвратить автоматическое удаление файла при закрытии. Ваш ответ в настоящее время подразумевает, что NamedTemporaryFile с delete = True можно открыть после его закрытия; этого не может быть, так как к этому моменту файл исчез.
@ user2357112: Учитывая, что рассматриваемый API работает с файлом название, является пытается его повторно открыть. Я указывал, что единственный способ «повторно открыть» его с помощью delete=True - это закрыть его (что удаляет его в процессе), а затем снова открыть это имя (учитывая, что API использует имена, он предположительно способен создать файл); как уже упоминалось, закрытие / удаление его перед использованием имени вводит гонку, в которой кто-то другой может использовать это имя. В моем примере кода, который позволяет избежать этой проблемы, используется delete=False, чтобы избежать гонки, но взамен он должен заново реализовать автоматическое удаление с нуля, что является проблемой.
В исходной формулировке не говорилось, что вы создадите новый файл, если попытаетесь открыть файл после закрытия с помощью delete=True. Ваша новая формулировка ... ну, она немного запутанно структурирована, но, по крайней мере, дает понять, что вы создаете новый файл. (Кроме того, по-видимому, вы может повторно открываете NamedTemporaryFile перед закрытием с помощью delete=False, поэтому либо OP в отчете о проблеме был неправильным, либо с тех пор что-то изменилось. Сначала я подумал, что это ошибка в вашем ответе.)
Почему вы пытаетесь использовать атрибут файла
nameв качестве диспетчера контекста?