user308827
user308827

Reputation: 21971

Using NamedTemporaryFile

with NamedTemporaryFile(suffix='.shp').name as tmp_shp:
    df.to_file(tmp_shp)

In code above, I get this error:

AttributeError: __enter__

How can I use a named temporary file using with statement? and since tmp_shp is just a path, does it still stay available outside of with?

Upvotes: 3

Views: 6993

Answers (3)

ShadowRanger
ShadowRanger

Reputation: 155418

The name attribute is a string; trying to access it in the with statement makes it the managed resource (and str has no concept of context management). You need to manage the NamedTemporaryFile itself, and access the name as needed:

with NamedTemporaryFile(suffix='.shp') as tmp_shp:
    df.to_file(tmp_shp.name)  # Access .name here, assuming you need a str

If to_file accepts file-like objects (I can't find docs for such a method), you'd avoid using .name at all (in either line).

Update: Because you're on Windows, you can't actually open a file opened by NamedTemporaryFile with delete=True (the default) until the NamedTemporaryFile is closed (which means you can't use any data written to that file handle, since it's deleted, and introduces a race condition even if using it solely to generate a unique name; the file is deleted at that point, so you're really just creating a new file, but someone else might race you to creating that file later). Best I can suggest here is to using it without deletion support to get a unique name, wrapping it to force deletion yourself, e.g.:

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)

Yeah, it's ugly. There aren't a lot of good options here; NamedTemporaryFile is fundamentally broken on Windows.

Upvotes: 6

Sraw
Sraw

Reputation: 20214

You should use with statement for NamedTemporaryFile itself but not its name attribute.

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?

And as the official doc, tmp_file will be deleted outside of with unless you pass delete=False to NamedTemporaryFile.

That means you should with NamedTemporaryFile(suffix='.shp', delete=False) as tmp_file:

Upvotes: 2

TwistedSim
TwistedSim

Reputation: 2030

You use the name attribute as a context manager. Try:

with NamedTemporaryFile(suffix='.shp') as tmp_shp:
    df.to_file(tmp_shp)

Upvotes: 1

Related Questions