[英]Keyboard interrupt, sockets and Threads
我正在使用套接字進行通信的接口上工作。 我需要使用線程才能同時接收和發送數據。
以下代碼是連續發送數據的模塊的簡化版本。
我的問題是,在開發過程中,我需要經常啟動和停止它,但是似乎線程使得無法像正常腳本一樣停止應用程序。 需要在進程管理器中終止該進程才能重新啟動它。
我有一種誤解。
我環顧四周,但看到大量不一致的答案,這些嘗試都沒有實現。 我已經嘗試處理KeyboardInterrupt異常,但是它不起作用。
有任何想法嗎?
import socket
import sys
import threading
running = True
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('localhost', 50000)
print ('connecting to %s port %s' % server_address)
sock.connect(server_address)
class TelemetryPacket:
state = "N/A"
def __init__(self, stringvalue):
self.state = stringvalue
def serialise(self):
return "%s" % (self.state)
def send(running):
try:
while (running):
telemetry = TelemetryPacket(0).serialise()
sock.sendto(telemetry.encode('utf-8'), server_address)
except KeyboardInterrupt:
print ("threads successfully closed")
running = False
def recv(running):
try:
while (running):
data = sock.recv(1)
if (data):
print("data received: %s" % data)
except KeyboardInterrupt:
print ("threads successfully closed")
running = False
a = threading.Thread(target=send, args=(running,))
a.start()
b = threading.Thread(target=recv, args=(running,))
b.start()
您應該在主線程中捕獲鍵盤中斷,然后向子線程發送信號以退出並重新加入主線程。 您還應該使用更多線程安全的信號進行傳輸,例如基本threading.Event()
,因此:
import threading
import time
exit_signal = threading.Event() # your global exit signal
def send():
while not exit_signal.is_set():
pass # whatever you need
def recv():
while not exit_signal.is_set():
pass # whatever you need
# create the threads
a = threading.Thread(target=send)
b = threading.Thread(target=recv)
# start the threads
a.start()
b.start()
# create a main thread loop
try:
while not exit_signal.is_set(): # enable children threads to exit the main thread, too
time.sleep(0.1) # let it breathe a little
except KeyboardInterrupt: # on keyboard interrupt...
exit_signal.set() # send signal to all listening threads
# join back the threads
a.join()
b.join()
# and you're done...
問題是在鍵盤異常情況下,僅主線程被殺死。 因此,您需要通知線程主線程已被殺死。
不用傳遞運行作為參數,而是用它來向線程發出信號。這里是一個示例代碼。 唯一的區別是該函數不以運行作為參數,而是使用它來跟蹤。 因此,當主線程死亡時,我們將其設置為false(在代碼末尾)。
import socket
import sys
import threading
running = True
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('localhost', 50000)
print ('connecting to %s port %s' % server_address)
sock.bind(server_address)
class TelemetryPacket:
state = "N/A"
def __init__(self, stringvalue):
self.state = stringvalue
def serialise(self):
return "%s" % (self.state)
def send():
try:
while (running):
telemetry = TelemetryPacket(0).serialise()
sock.sendto(telemetry.encode('utf-8'), server_address)
except KeyboardInterrupt:
print ("threads successfully closed")
def recv():
try:
while (running):
data = sock.recv(1)
if (data):
print("data received: %s" % data)
except KeyboardInterrupt:
print ("threads successfully closed")
try:
a = threading.Thread(target=send)
a.start()
b = threading.Thread(target=recv)
b.start()
while True:
pass
except KeyboardInterrupt:
print ("threads successfully closed")
running = False # Kill the threads
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.