Python 終了方法 sys.exit(), os._exit(), Ctrl+Z, Ctrl+C

uBuntuでは終了できてもPetalinuxでは終了できなかったりするので、調べたいろいろな方法を残しておきます。

強さの順番

これは間違っているかもしれませんが、私の環境では以下の順で効きました。

  1. os._exit()
  2. sys.exit()
  3. exit()
  4. Ctrl+Z=>Ctrl+C

Ctrl+Zは中断するだけなので、実行したプログラムプロセスもそのままだし、socketやポート等も解放していないので同じプログラムを再度起動して同じポートを使おうとしたら『Address already in use (addr=’tcp://*:50000′) 』の様にエラーで実行できない事になります。

Exceptionエラー

これが発生すると、プログラムが止まってしまってキーボードを受け付けなくなるので、このエラーが発生するところはtry~exceptで逃げて、最終的にはsys.exit()かos._exit()できちんと終了してポートやプロセスなどを開放してあげましょう。(こんな感じでCtrl+Cも効きません。

このようになったら、別のターミナルから以下の手順でkillすると復活します。

  • psで起動したプログラムファイル名で探して、
  • 表示されたプロセスIDでそのプロセスを強制終了する。
petalinux@peta:~$ ps aux|grep opc_zmq_rep.py
  913 petalinu  0:01 python opc_zmq_rep.py
  951 petalinu  0:00 grep zmq
petalinux@peta:~$ kill -9 913

面倒なのでプログラムでexceptでos_exit(1)をしておくと確実にリソースを開放して終了できます。因みにexit(1)の『1』は異常終了、『0』の場合は正常終了とする決まりだそうです。

exceptで終了する場合

import os

try:
    socket.bind("tcp://*:50000")
except zmq.error.ZMQError as e:
    print("ZMQError:", e)
    os._exit(1)

Ctrl+ZでもCtrl+Cでも終了する場合

Ctrl+ZでもCtrl+Cでも正常終了しないので、正常終了したい場合は以下の様にCtrl+ZやCtrl+Cをキャッチして終了するようにします。

import os

def signal_handler(sig, frame):
    print('Ctrl+C or Ctrl+Z was pressed. Terminate this program.')
    os._exit(0)

# Ctrl+C(SIGINT)をキャッチ
signal.signal(signal.SIGINT, signal_handler)
# Ctrl+Z(SIGTSTP)をキャッチ
signal.signal(signal.SIGTSTP, signal_handler)

Ctrl+CとCtrl+Zで操作を分けたい場合は

import os

def signal_handler(sig, frame):
    if sig==signal.SIGINT:
        print('Ctrl+C was pressed. Terminate this program.')
    if sig==signal.SIGTSTP:
        print('Ctrl+Z was pressed. Terminate this program.')
    os._exit(0)

# Ctrl+C(SIGINT)をキャッチ
signal.signal(signal.SIGINT, signal_handler)
# Ctrl+Z(SIGTSTP)をキャッチ
signal.signal(signal.SIGTSTP, signal_handler)

コメント