Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stopping a python process so that context managers still call __exit__ (in windows)

Tags:

python

windows

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
like image 341
Batman0730 Avatar asked Jul 19 '17 19:07

Batman0730


1 Answers

I found a workaround on the PyCharm bug tracker:

https://youtrack.jetbrains.com/issue/PY-17252

  • In PyCharm go to help->Edit Custom Properties
  • Agree to create the idea.properties file (if it asks)
  • Add the following line: kill.windows.processes.softly=true
  • 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
like image 95
Batman0730 Avatar answered Oct 07 '22 23:10

Batman0730