1

Given this code:

from time import sleep

class TemporaryFileCreator(object):
  def __init__(self):
    print 'create temporary file'
    # create_temp_file('temp.txt')

  def watch(self):
    try:
      print 'watching tempoary file'
      while True:
        # add_a_line_in_temp_file('temp.txt', 'new line')
        sleep(4)
    except (KeyboardInterrupt, SystemExit), e:
      print 'deleting the temporary file..'
      # delete_temporary_file('temp.txt')
      sleep(3)
      print str(e)



t = TemporaryFileCreator()
t.watch()

during the t.watch(), I want to close this application in the console..

I tried using CTRL+C and it works: enter image description here

However, if I click the exit button:
enter image description here

it doesn't work.. I checked many related questions about this but it seems that I cannot find the right answer..

What I want to do:

The console can be exited while the program is still running.. to handle that, when the exit button is pressed, I want to make a cleanup of the objects (deleting of created temporary files), rollback of temporary changes, etc..

Question:

  1. how can I handle console exit?
  2. how can I integrate it on object destructors (__exit__())
  3. Is it even possible? (how about py2exe?)

Note: code will be compiled on py2exe.. "hopes that the effect is the same"

catzilla
  • 1,901
  • 18
  • 31
  • umm, what? When you hit the X doesn't the application gets killed by the OS? – gsamaras Mar 21 '16 at 08:38
  • @gsamaras, yes, however I want to do some object cleanup after the x button is pressed.. that's why.. I'll add it in my question.. – catzilla Mar 21 '16 at 08:40
  • when you hit X button you are killing parent process of your python process ... when you hit CTRL+C you Interrupt your python process , and it goes inside your exception handling block ... what i mean is hitting X button doesnt lead your program to exception handling block, and my question is what do u want to do ? – Sepehr Hamzehlooy Mar 21 '16 at 08:41
  • @SepehrHamzelooy, I updated my question, I'm hoping that it is clear enough.. – catzilla Mar 21 '16 at 08:44
  • you cant lead your program to do something when you are killing its parent process , imagine you are pressing and holding physical button of your computer(i mean killing your computer power) and ask your Operating System to do something for you after it . – Sepehr Hamzehlooy Mar 21 '16 at 08:47
  • Good place to have cleanup stuff is `finally`. – GingerPlusPlus Mar 21 '16 at 08:52
  • @SepehrHamzelooy, thank you for your informative comment, it seems that it is quite true and logical.. however, I will still (desperately) try to wait for an answer that would(hopefully) make the impossible possible.. XD – catzilla Mar 21 '16 at 08:58

2 Answers2

2

You may want to have a look at signals. When a *nix terminal is closed with a running process, this process receives a couple signals. For instance this code waits for the SIGHUB hangup signal and writes a final message. This codes works under OSX and Linux. I know you are specifically asking for Windows but you might want to give it a shot or investigate what signals a Windows command prompt is emitting during shutdown.

import signal
import sys
def signal_handler(signal, frame):
            with open('./log.log', 'w') as f:
                f.write('event received!')

signal.signal(signal.SIGHUP, signal_handler)
print('Waiting for the final blow...')
#signal.pause() # does not work under windows
sleep(10) # so let us just wait here

Quote from the documentation:

On Windows, signal() can only be called with SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, or SIGTERM. A ValueError will be raised in any other case.

Update:

Actually, the closest thing in Windows is win32api.setConsoleCtrlHandler (doc). This was already discussed here:

When using win32api.setConsoleCtrlHandler(), I'm able to receive shutdown/logoff/etc events from Windows, and cleanly shut down my app.

And if Daniel's code still works, this might be a nice way to use both (signals and CtrlHandler) for cross-platform purposes:

import os, sys
def set_exit_handler(func):
    if os.name == "nt":
        try:
            import win32api
            win32api.SetConsoleCtrlHandler(func, True)
        except ImportError:
            version = “.”.join(map(str, sys.version_info[:2]))
            raise Exception(”pywin32 not installed for Python ” + version)
    else:
        import signal
        signal.signal(signal.SIGTERM, func)

if __name__ == "__main__":
    def on_exit(sig, func=None):
        print "exit handler triggered"
        import time
        time.sleep(5)

set_exit_handler(on_exit)
print "Press  to quit"
raw_input()
print "quit!"
Community
  • 1
  • 1
aleneum
  • 2,083
  • 12
  • 29
  • this answer works closest to what I'm looking for.. I will try this first and it seems that the signal `SIGTERM` is what I'm looking for.. gotta check this out. – catzilla Mar 21 '16 at 10:09
1

If you use tempfile to create your temporary file, it will be automatically deleted when the Python process is killed.

Try it with:

>>> foo = tempfile.NamedTemporaryFile()
>>> foo.name
'c:\\users\\blah\\appdata\\local\\temp\\tmpxxxxxx'

Now check that the named file is there. You can write to and read from this file like any other.
Now kill the Python window and check that file is gone (it should be)

You can simply call foo.close() to delete it manually in your code.

SiHa
  • 7,830
  • 13
  • 34
  • 43