How can I stop a python process in such a way that any active context managers will gracefully call their __exit__ function before closing?
I use context managers (__enter__() and __exit__()) to reliably and safely close connections to optical hardware. This has been working great, although we are now starting to execute routines that run for hours. Often we will realize shortly after starting one that we have a bug, and would rather to stop the process short.
I have been running code from PyCharm, which has allows you to "stop" a running process. This seems to instantly kill the process, whether I'm in debug or run. The __exit__ functions don't seem to get called.
Also, the computer that controls the hardware runs windows, if that somehow comes into play. ***
***Indeed in comes into play. Macosx seems to call the exit function while windows does not.
I decided to write a basic test:
from abc import *
import time
class Test(object):
__metaclass__ = ABCMeta
def __init__(self, *args, **kwargs):
print("Init called.")
def __enter__(self, *args, **kwargs):
print("enter called")
def __exit__(self, type, value, traceback):
print("Exit called")
with Test() as t:
time.sleep(100)
print("Should never get here.")
I run this code from PyCharm, and while it is in the sleep statement I press the stop button in pycharm. Here is the output from both:
Macosx:
Init called.
enter called
Exit called
Traceback (most recent call last):
File "/Applications/PyCharm CE.app/Contents/helpers/pydev/pydevd.py", line 1591, in <module>
globals = debugger.run(setup['file'], None, None, is_module)
File "/Applications/PyCharm CE.app/Contents/helpers/pydev/pydevd.py", line 1018, in run
pydev_imports.execfile(file, globals, locals) # execute the script
File "/Users/.../Library/Preferences/PyCharmCE2017.1/scratches/scratch_25.py", line 22, in <module>
time.sleep(100)
KeyboardInterrupt
Windows
Init called.
enter called
Process finished with exit code 1
I found a workaround on the PyCharm bug tracker:
https://youtrack.jetbrains.com/issue/PY-17252
If you use Numpy or Scipy, you will also need to add the following environment variable:
os.environ['FOR_DISABLE_CONSOLE_CTRL_HANDLER'] = "1"
Restart Pycharm
Now when I run my test with this applied (on Windows!) I get the following output:
Init called.
enter called
Exit called
Traceback (most recent call last):
File "C:/Users/.../.PyCharmCE2017.1/config/scratches/scratch_3.py", line 20, in <module>
time.sleep(100)
KeyboardInterrupt
Process finished with exit code 1
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