bluelemonade
bluelemonade

Reputation: 1305

how to close python process on program end

I fail to close a serial connection that runs in a process properly at the end of the program. (on windows/VSCode and Ctrl-C)

I get an error message and most of the time the port is already opened at the next start of the program.

Do I have to finish the run process first?

class serialOne(Process):
    def __init__(self, serial_port, debug, baudrate=57600, timeout=1):
    ...

    def terminate(self):
        print("close ports")
        self.active = False
        self.ser.close()

    def run(self):
        while self.active:
            self.initCom()
            self.readCom()
            time.sleep(0.005)

    def main():
        global processList
        global debug

        while True:
            if debug == True:
                print("main")
            time.sleep(1.0)

        for process in processList:
            process.terminate()

and my main:

def main():
    global processList
    global debug

    while True:
        if debug == True:
            print("main") # actually doing nothing
        time.sleep(1.0)

    for process in processList:
        process.terminate()

that's the error message:

Process serialOne-1:
Traceback (most recent call last):
  File "C:\Users\dgapp\AppData\Local\Programs\Python\Python37-32\lib\multiprocessing\process.py", line 297, in _bootstrap
    self.run()
Traceback (most recent call last):
  File "e:\_python\rfid_jacky\simple_multiprocess_rfid_02.py", line 129, in run
    time.sleep(0.005)
  File "c:\Users\dgapp\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\ptvsd_launcher.py", line 45, in <module>
KeyboardInterrupt
    main(ptvsdArgs)
  File "c:\Users\dgapp\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\lib\python\ptvsd\__main__.py", line 265, in main
    wait=args.wait)
  File "c:\Users\dgapp\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\lib\python\ptvsd\__main__.py", line 258, in handle_args
    debug_main(addr, name, kind, *extra, **kwargs)
  File "c:\Users\dgapp\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\lib\python\ptvsd\_local.py", line 45, in debug_main
    run_file(address, name, *extra, **kwargs)
  File "c:\Users\dgapp\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\lib\python\ptvsd\_local.py", line 79, in run_file
    run(argv, addr, **kwargs)
  File "c:\Users\dgapp\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\lib\python\ptvsd\_local.py", line 140, in _run
    _pydevd.main()
  File "c:\Users\dgapp\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\lib\python\ptvsd\_vendored\pydevd\pydevd.py", line 1925, in main
    debugger.connect(host, port)
  File "c:\Users\dgapp\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\lib\python\ptvsd\_vendored\pydevd\pydevd.py", line 1283, in run
    return self._exec(is_module, entry_point_fn, module_name, file, globals, locals)
  File "c:\Users\dgapp\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\lib\python\ptvsd\_vendored\pydevd\pydevd.py", line 1290, in _exec
    pydev_imports.execfile(file, globals, locals)  # execute the script
  File "c:\Users\dgapp\.vscode\extensions\ms-python.python-2018.12.1\pythonFiles\lib\python\ptvsd\_vendored\pydevd\_pydev_imps\_pydev_execfile.py", line 25, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "e:\_python\rfid_jacky\simple_multiprocess_rfid_02.py", line 161, in <module>
    main()
  File "e:\_python\rfid_jacky\simple_multiprocess_rfid_02.py", line 140, in main
    time.sleep(1.0)
KeyboardInterrupt

Upvotes: 0

Views: 1081

Answers (2)

olinox14
olinox14

Reputation: 6663

The KeyboardInterrupt happens when the user hits the interrupt key.

A simple solution would be to catch the exception:

while True:
    if debug == True:
        print("main") # actually doing nothing

    try:
        # do your things
    except KeyboardInterrupt:
        print("program was interrupted by user")
        break

You could also use the finally keyword to properly end your program:

try:
    while True:
        # do your things    
except KeyboardInterrupt:
    print("program was interrupted by user")
    break
finally:
    close()  # this will always happen, even if an exception was raised

Upvotes: 0

Schnouki
Schnouki

Reputation: 7717

When you press Ctrl+C, a KeyboardInterrupt exception is thrown, and interrupts your infinite sleep loop. But since you don't catch this exception, the code after this loop (with process.terminate()) is never called, which probably causes your issue.

So you have several options:

  • catch KeyboardInterrupt and use that to exit the inifite loop:

    def main():
        global processList
        global debug
    
        try:
            while True:
                if debug == True:
                    print("main") # actually doing nothing
                time.sleep(1.0)
        except KeyboardInterrupt:
            pass
    
        for process in processList:
            process.terminate()
    

    Which is simple and very readable.

  • register an exit handler that will be run when your program exits:

    import atexit
    
    @atexit.register
    def shutdown():
        global processList
    
        for process in processList:
            process.terminate()
    
    def main():
        global debug
    
        while True:
            if debug == True:
                print("main") # actually doing nothing
            time.sleep(1.0)
    

    Which is more reliable since it will work even if your process is terminated by another signal.

Upvotes: 1

Related Questions