Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/341.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Python中实现多线程?[套接字编程]_Python_Multithreading_Python 3.x_Sockets - Fatal编程技术网

如何在Python中实现多线程?[套接字编程]

如何在Python中实现多线程?[套接字编程],python,multithreading,python-3.x,sockets,Python,Multithreading,Python 3.x,Sockets,我试图在客户机中创建一个单独的线程,以非阻塞方式从服务器套接字恢复消息。由于我的原始代码太长,而且为了理解它而解释起来有点麻烦,所以我创建了一个示例程序,重点介绍我想要做的事情。我尝试创建两个独立的线程,比如线程t1和线程t2线程t1轮询套接字以检查是否有任何接收到的数据,而线程t2执行分配给它的任何任务。我希望它做的是,线程t1总是轮询,如果收到数据,它会在屏幕上打印数据,线程t2并行执行它正在做的任何事情。但是,由于某些原因,我无法让它工作 我的示例程序是: import threading

我试图在客户机中创建一个单独的线程,以非阻塞方式从服务器套接字恢复消息。由于我的原始代码太长,而且为了理解它而解释起来有点麻烦,所以我创建了一个示例程序,重点介绍我想要做的事情。我尝试创建两个独立的线程,比如
线程t1
线程t2
<代码>线程t1轮询套接字以检查是否有任何接收到的数据,而
线程t2
执行分配给它的任何任务。我希望它做的是,
线程t1
总是轮询,如果收到数据,它会在屏幕上打印数据,
线程t2
并行执行它正在做的任何事情。但是,由于某些原因,我无法让它工作

我的示例程序是:

import threading
import time
import threading
from time import sleep
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 5555))
s.setblocking(0)
s.sendall(str.encode('Initial Hello'))

def this_thing():
    while True:
        try:
           data = s.recv(4096)
            print(data.decode('utf-8'))
        except:
            pass / break #not sure which one to use. Neither of it works

def that_thing():
    for i in range(10000):
        sleep(3)
        s.sendall(str.encode('Hello')
        print('happening2')

threading.Thread(target=this_thing(), args=[]).start()
threading.Thread(target=that_thing(), args=[]).start()
注意:服务器套接字是一个简单的服务器,如果收到消息,它会向所有连接的套接字发送消息。
当我通过
线程t1
中的异常来运行程序时,只有
线程t2
保持运行。也就是说,
线程t1
没有收到从服务器发送的任何数据

发生这种情况的原因是“target”参数接受了一个可调用的对象

从docs.python.org/2/library/threading.html

“target是run()方法调用的可调用对象”

在你的版本中

threading.Thread(target=this_thing(), args=[]).start()
threading.Thread(target=that_thing(), args=[]).start()
当您说target=this_thing()时,它将尝试计算对该_thing调用的值,在您的情况下,它将进入while True循环,然后如果要完成,它将计算为None

您要做的是将这两行替换为

threading.Thread(target=this_thing, args=[]).start()
threading.Thread(target=that_thing, args=[]).start()

请注意,您现在正在传入函数本身。函数是可调用的对象。

python 3+的正确解决方案不是多线程,而是异步

查看David Beazley关于此事的精彩演讲(49分钟):


Asyncio/sockets示例:

您不应该传入except块,捕获异常并记录它,或者只是打印它。若要捕获任何可以执行的异常,请尝试:code(),但异常为e:print(e)。异常越具体越好。@chatton:异常是:
[WinError 10035]非阻塞套接字操作无法立即完成
,这是有道理的,但是如果我将套接字更改为阻塞,它永远不会真正离开
线程t1
,直到我收到一条我不想做的消息。有没有办法解决这个问题?threading.Thread(target=this_thing(),args=[]).start(),我很确定目标应该是函数本身,而不是函数调用的结果。target=this_thing()->target=this_thing我认为现在发生的事情是,在创建第一个线程的过程中,它被卡在一个无限循环中,这个东西和那个东西是可调用的对象。您应该能够简单地将target=this\u thing()更改为target=this\u thing,对那个东西也是一样