본 포스팅에서는 Linux 및 Windows OS에서 SIGINT 및 SIGBREAK 와 같은 운영 체제 신호를 캡처하고 처리하여 실행 중에 Python 스크립트의 흐름을 제어하는 방법을 배웁니다 . Python 3의 신호 모듈을 사용하여 OS 신호를 캡처하고 처리합니다.
이 튜토리얼에서는 SIGINT(CTRL +C ), SIGBREAK(CTRL+BREAK)와 같은 OS 신호를 포착하는 사용자 지정 신호 핸들러(custom signal handler)를 직접 작성하는 방법을 알려드립니다,
사용자 지정 신호 처리기에 신호를 등록하고 기본 신호 동작을 재정의하는 방법을 알아보고, 파이썬에서 무한 루프에서 빠져나오기 위해 SIGINT, SIGBREAK를 사용하고 Linux 및 Windows 시스템에서 파일 객체, 직렬 연결 등과 같은 열려 있는 리소스를 질서정연하게 닫습니다.
아래 예시에서는 다음과 같은 방식으로 지속적으로 무언가를 수행하는 무한 루프가 있습니다. 예를 들어 직렬 포트에서 데이터를 지속적으로 읽어 파일에 쓰는 무한 루프를 가정합니다.
while 1:
read from port()
이제 스크립트가 수행하던 작업을 중지하고 직렬 포트 개체 또는 파일 개체와 같은 열려 있는 모든 리소스를 닫는 동안 정상적으로 종료하려고 합니다. 여기에서 OS 신호를 사용하여 무한 루프 실행을 중단할 수 있습니다.
신호란 무엇인가?
신호는 프로그램 또는 프로세스(여기서는 Python 스크립트)가 키보드 누름(CTRL + C) 또는 오류와 같은 특정 이벤트가 발생한 운영 체제로부터 정보를 수신할 수 있는 방법입니다. 신호는 OS에 의해 정수 값으로 할당됩니다.
키보드에서 CTRL + C를 누르면 운영 체제(Windows 및 Linux 모두) 는 현재 활성화된 프로그램으로 전송되는 SIGINT 신호를 생성합니다 . 수신 프로그램은 SIGINT 신호에 의해 지정된 기본 기능을 실행할 수 있습니다.
또는 신호 처리기를 사용하여 SIGINT 신호를 트랩하고 사용자 정의 사용자 지정 함수를 실행할 수 있습니다. 모든 시스템에서 모든 신호를 사용할 수 있는 것은 아닙니다. 운영 체제(Linux/Windows) 간에 정의된 시스템의 신호(할당 정수 혹은 기능)가 다름니다.
OS에서 사용 가능한 신호를 확인합니다. 모든 OS에서 모든 신호를 사용할 수 있는 것은 아니므로 시스템에서 사용할 수 있는 신호를 아는 것이 좋습니다. 여기서는 Python 3(Python 3.9.x)을 사용하고 신호에 액세스하려면 신호 모듈을 가져와야 합니다.
아래는 파이선에서 OS 신호 종류를 보여주는 코드입니다. python_available_signals.py
#OS Signal Handling in Python 3.x.x
#Display available signals on our System
#www.xanthium.in
import signal # Import signal module using the import keyword
import platform # for identifying the OS
import pprint # for pretty print
# available signals on our System
valid_signals = signal.valid_signals() # requires python 3.9.0
# returns a SET
#print('Available Signals ->',valid_signals)
print('\n\nOperating System ->',platform.platform())
print('Number of Available Signals ->', len(valid_signals) , '\n')
pprint.pprint(valid_signals)#using pretty print to display set datastructure
위 파이선 스크립트를 실행한 결과는 아래와 같습니다.
윈도우 10에서 사용 가능한 OS 신호
Operating System -> Windows-10-10.0.22621-SP0
Number of Available Signals -> 7
{<Signals.SIGINT: 2>,
<Signals.SIGILL: 4>,
<Signals.SIGFPE: 8>,
<Signals.SIGSEGV: 11>,
<Signals.SIGTERM: 15>,
<Signals.SIGBREAK: 21>,
<Signals.SIGABRT: 22>}
리눅스에서 사용가능한 Signal 종류는 위 프로그램이 버전 3.9라서 에러가 나서 그냥 리눅스 시스템 명령어로 긁어 왔습니다.
kill -l
결과는 아래와 같습니다. 아주 아름답게 출력이 되네요~^^
(base) tako@rtx-a5000:~/pythontest$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
위의 결과에서 볼 수 있듯이 Linux 및 Windows 시스템에서 사용할 수 있는 신호의 수와 유형에는 상당한 차이가 있습니다.
Python 3에서 신호 프로그래밍
스크립트에서 받은 신호를 사용하려면 두 가지 작업을 수행해야 합니다.
1. 신호가 수신되면 사용자 지정 처리를 수행할 신호 처리기를 작성합니다 .
2. 신호 처리기 기능으로 신호 등록
import signal
def your_custom_signal_handler(signal_number,frame):
code to do something
code to do something
code to do something
signal.signal(signal.SIGNALNAME,your_custom_signal_handler)
여기서는 SIGINT 신호를 사용하여 Python 3 스크립트의 실행을 제어합니다. SIGINT 신호는 Windows 및 Linux 시스템 모두에 공통적이며 Windows 및 Linux 시스템 모두에서 코드를 실행하는 데 도움이 됩니다. Github의 코드를 사용하십시오
import signal # Import signal module
def SignalHandler_SIGINT(SignalNumber,Frame):
print('SignalHandler of signal.SIGINT')
#register the signal with Signal handler
signal.signal(signal.SIGINT,SignalHandler_SIGINT)
while 1:
print("Press Ctrl + C ")
time.sleep(1)
아래는 SIGINT 신호를 처리하는 전체 코드입니다.
#OS Signal Handling in Python 3.x.x
#using Signals in Python 3.x.x
#Signals.SIGINT: CTRL + C ,Default action is to raise KeyboardInterrupt.
#www.xanthium.in
import signal # Import signal module using the import keyword
import time # available signals on your system
# Create a Signal Handler for Signals.SIGINT: CTRL + C
def SignalHandler_SIGINT(SignalNumber,Frame):
print('SignalHandler of signal.SIGINT')
print(f'Signal Number -> {SignalNumber} Frame -> {Frame}')
# Register the Signal Handler def SignalHandler_SIGINT() with the Signal
# signal.signal(Signal Name,Name of Handler Function)
signal.signal(signal.SIGINT,SignalHandler_SIGINT)
while 1:
print("Press Ctrl + C ")
time.sleep(1)
Python SIGINT 신호 코드 작업
위의 코드를 실행하면,
- Python 스크립트는 무한 루프에서 "Press CTRL + C"를 인쇄합니다.
- 키보드에서 CTRL + C를 누르면 OS(Windows/Linux)에서 SIGINT 신호가 생성되어 실행 중인 스크립트로 전송됩니다.
- 그런 다음 Python 스크립트는 def SignalHandler_SIGINT (SignalNumber,Frame): 스크립트 내부의 신호 처리기로 컨트롤을 전송한 다음 "SignalHandler of signal.SIGINT" 아래에서 인쇄 문을 실행합니다.
- 그런 다음 제어가 다시 무한 루프로 전환됩니다.
실행은 아래와 같습니다.
Python의 무한 루프에서 안전하게 종료
이 예제에서는 신호를 사용하여 Python 3의 무한 루프에서 안전하게 종료하는 방법을 배웁니다.
Python으로 작성된 직렬 포트 데이터 수집 시스템 소프트웨어와 같은 일부 응용 프로그램에서는 무한 루프에서 Arduino 또는 Raspberry Pi 보드와 같은 센서 또는 마이크로 컨트롤러를 지속적으로 쿼리해야 합니다.
이러한 애플리케이션에서는 SIGINT 신호(CTRL +C)를 사용하여 무한 루프를 중단하고 리소스 누수 없이 애플리케이션을 안전하게 닫을 수 있습니다.
SIGBREAK(CTRL + BREAK) 신호를 사용하여 그렇게 할 수도 있지만 신호는 Windows에서만 사용할 수 있지만 SIGINT는 Linux와 Windows 모두에서 사용할 수 있습니다.
아래는 무한 루프에서 시그널을 받아 처리하는 전체 코드입니다.
# OS Signal Handling in Python 3.x.x
# using signals to get out of an infinite loop
# Signal used is Signals.SIGINT: CTRL + C
# www.xanthium.in
import signal # Import signal module using the import keyword
import time # available signals on your system
Sentry = True
# Create a Signal Handler for Signals.SIGINT: CTRL + C
def SignalHandler_SIGINT(SignalNumber,Frame):
print('SignalHandler of signal.SIGINT')
#print(f'Signal Number -> {SignalNumber} Frame -> {Frame}')
global Sentry
Sentry = False
signal.signal(signal.SIGINT,SignalHandler_SIGINT) #register the signal handler
while Sentry:
print('Long continous event Eg,Read from sensor,Press CTRL+C to exit')
time.sleep(1)
print('Out of the while loop')
print('Clean up Here')
위 코드가 실행하는 방법은 아래와 같습니다.
- 이제 위의 코드에서 우리는 Sentry 변수를 사용하여 하단에 있는 while 루프의 흐름을 제어합니다.
- Sentry 변수는 스크립트가 처음 실행되고 while 루프가 계속 실행될 때 True, Sentry = True 로 설정됩니다 .
- 사용자가 루프를 중지하고 싶을 때 CTRL + C를 눌러 SIGINT 신호를 생성할 수 있습니다.
- SIGINT 신호 처리기가 실행되고 Sentry 변수를 False 로 설정합니다.
- 그런 다음 컨트롤은 Sentry == False 인 While 루프로 전달 되어 루프가 종료되고 컨트롤이 아래의 print() 문으로 전달됩니다.
- 사용자는 그곳에서 정리를 할 수 있습니다.
Sentry는 신호 처리기 내에서 Global로 정의해야 합니다.
Windows에서 Python의 무한 루프에서 벗어나기
SIGINT를 사용하여 Linux의 Python에서 무한 루프에서 벗어나기
참고자료
Capturing and Handling OS signals like SIGINT (CTRL-C) in Python
'개발자 > 파이썬 Python' 카테고리의 다른 글
Happy New Year 2024 하트 표시 만드는 파이선 코드 (2) | 2024.01.05 |
---|---|
아스키코드는 0~127입니다. (1) | 2023.11.27 |
Tiny Python Projects 강의 영상과 소스코드 (0) | 2023.08.14 |
파이썬에서 가장 많이 사용하는 상위 40개 라이브러리 (1) | 2023.06.26 |
Complete Python Roadmap for beginners in 2023 (0) | 2023.02.21 |
파이썬 파일 폴더 조작 총정리 Python - File, directory manipulation (0) | 2023.02.18 |
파이선 네이버 검색 키워드 분석 코드 (1) | 2023.02.16 |
OpenCV 4로 배우는 컴퓨터 비전과 머신 러닝 (0) | 2023.02.10 |
더욱 좋은 정보를 제공하겠습니다.~ ^^