The following Python 3 code exhibits some strange behavior (to me, at least) when I run it through strace
:
import os
import sys
if len(sys.argv) != 2:
print('Usage: ecpy <filename>')
sys.exit(1)
try:
print('my PID: %d' % os.getpid())
with open(sys.argv[1], 'w') as fp:
try:
fp.write('Hello Stack Overflow!')
except IOError as e:
print('### before close')
print(str(e))
sys.stdout.flush()
except IOError as e:
print('### after close')
print(str(e))
sys.stdout.flush()
print('### after exception block')
sys.stdout.flush()
Since I/O is buffered, if you run this code with /dev/full
, it doesn't fail until fp
closes at the end of the with
block. That's no surprise. In Python 2.7.3rc2 (on my system), the code runs the exception handler after actually closing the file descriptor corresponding to fp
:
write(3, "Hello Stack Overflow!", 21) = -1 ENOSPC (No space left on device)
close(3) = 0
munmap(0x7f9de3f78000, 4096) = 0
write(1, "### after close\n", 16) = 16
write(1, "[Errno 28] No space left on devi"..., 35) = 35
write(1, "### after exception block\n", 26) = 26
However, in Python 3.2.3 (on my system), the file descriptor is still open after the exception block runs:
write(3, "Hello Stack Overflow!", 21) = -1 ENOSPC (No space left on device)
write(1, "### after close\n", 16) = 16
write(1, "[Errno 28] No space left on devi"..., 35) = 35
write(1, "### after exception block\n", 26) = 26
...
write(3, "Hello Stack Overflow!", 21) = -1 ENOSPC (No space left on device)
write(3, "Hello Stack Overflow!", 21) = -1 ENOSPC (No space left on device)
close(3) = 0
The interpreter tries to write to the file a few more times and fails silently. When does Python actually call close()
? What is invoking it? This behavior seems to leak a file descriptor.
I took the liberty of submitting an issue to bugs.python.org, let's wait and see if it pans out.
http://bugs.python.org/issue16597
EDIT: Looks like it's a bug, good catch!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With