Python 键盘中断、套接字和线程

Python 键盘中断、套接字和线程,python,multithreading,sockets,Python,Multithreading,Sockets,我正在开发一个使用套接字进行通信的接口。我需要使用线程来同时接收和发送数据 下面的代码是连续发送数据的模块的精简版本 我的问题是,在开发过程中,我需要频繁地启动和停止这个程序,但线程似乎不可能像普通脚本那样停止应用程序。需要在process manager中终止该进程才能重新启动它 我觉得我误解了什么 我环顾了一下四周,但我看到了大量不一致的答案,我试图实现这些答案,但都无济于事。我尝试过处理键盘中断异常,但没有效果 有什么想法吗 import socket import sys import

我正在开发一个使用套接字进行通信的接口。我需要使用线程来同时接收和发送数据

下面的代码是连续发送数据的模块的精简版本

我的问题是,在开发过程中,我需要频繁地启动和停止这个程序,但线程似乎不可能像普通脚本那样停止应用程序。需要在process manager中终止该进程才能重新启动它

我觉得我误解了什么

我环顾了一下四周,但我看到了大量不一致的答案,我试图实现这些答案,但都无济于事。我尝试过处理键盘中断异常,但没有效果

有什么想法吗

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()

问题是,在键盘异常中,只有主线程被终止。 因此,您需要通知线程主线程已被终止

不要将running作为参数传递,而是使用它向线程发送信号。唯一的区别是函数不把running作为参数,而是用它来跟踪。因此,当主线程死亡时,我们将其设置为false(在代码末尾)


您应该在主线程中捕获键盘中断,然后向子线程发送一个信号以退出并连接回主线程。您还应该使用更安全的线程来发送信号,比如基本的
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...

sock=socket.socket(socket.AF\u INET,socket.sock\u STREAM)
我需要使用线程来同时接收和发送数据。首先,了解socket库。您无法使用TCP连接编写实时应用程序@dsgdfg你说得很好。我假设只有一种类型的“socket”,所以我假设这个库都是UDP,而没有真正思考。这只是一个原型,所以现在还可以。我以后一定会研究一个合适的解决方案,谢谢!谢谢,在最高级别捕获中断有助于我理解线程问题。我还必须添加一个socket.close()使其能够很好地工作。这是一个非常好的答案。我想我现在更了解这一点了,结构比我以前做的要干净得多,因为只有一次尝试/捕获,它使用事件而不是bool。我只需要在异常处理程序中添加一个socket.close(),现在它就可以正常工作了!谢谢
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...