Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ZstdCompressionWriter.__exit__() not always calling close() is confusing #86

Closed
cstoitner opened this issue Jul 16, 2019 · 3 comments
Closed

Comments

@cstoitner
Copy link

cstoitner commented Jul 16, 2019

When I first tried to use this library I ended up with code that, when reduced, looked something like this:

if __name__ == "__main__":
    cctx = zstd.ZstdCompressor(level=10)
    with open('workfile', 'wb') as fh, cctx.stream_writer(fh) as compressor:
        compressor.write(b'chunk 0')
        exit(0)

It produced an empty file, and I had no idea what I had done wrong. Out of frustration I added compressor.close() before the exit call - and suddenly it worked! Why did the context manager not call close() for me?

As far as I can tell ZstdCompressionWriter (and probably other classes) will never call close() when an exception is raised inside the with statement (exit() is implemented with an exception). I don't think this is a good idea. In my opinion with statements should always try to properly release their resources. This also goes against the documentation of pythons file objects:

It is good practice to use the with keyword when dealing with file objects. The advantage is that the file is properly closed after its suite finishes, even if an exception is raised at some point.

The current design can easily lead to brittle code that seems to work in the absence of exceptions but will not actually write the whole output to a file as soon as something goes wrong somewhere else - even though the script looks like it has proper error handling implemented.

@indygreg
Copy link
Owner

indygreg commented Aug 1, 2019

This issue is very similar to #76. Should this issue be marked as a duplicate? Should discussion continue in #76?

(I concede that the behavior of context managers and close() currently has some corner cases. There's not a trivial, one-size-fits-all solution.)

@cstoitner
Copy link
Author

cstoitner commented Aug 2, 2019

I think these 2 issues don't quite belong together. Even if file handling is completely removed from ZstdCompressionWriter I still would expect the context manager to always do the same thing in __exit__(). This bug is not so much about what close() actually does, but about __exit__() behaving differently in case of exceptions (this might not have been clear enough in my initial report).

Right now the context manager implementation in ZstdCompressionWriter seems pretty useless to me. I always use an additionally finally: writer.close() block, making the with statement redundant.

@indygreg
Copy link
Owner

I agree that we should unconditionally call close() from __exit__(). I'll make this change for the next release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants