Python中的线程同步 [英] Thread synchronization in Python

查看:78
本文介绍了Python中的线程同步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在从事一个学校项目,除其他事项外,任务是建立线程服务器/客户端系统.系统中的每个客户端在连接到服务器时都应该在服务器上分配有自己的线程.另外,我希望服务器运行其他线程,一个与命令行输入有关,另一个与向所有客户端广播消息有关.但是,我无法像我想要的那样运行它.线程之间似乎相互阻塞.我希望程序在服务器侦听连接的客户端的相同时间"从命令行获取输入,依此类推.

我是python编程和多线程技术的新手,尽管我认为我的想法很好,但我并不惊讶我的代码行不通.问题是我不确定如何实现在不同线程之间传递的消息.我也不确定确切如何正确实施资源锁定命令.我将在此处发布服务器文件和客户端文件的代码,希望有人可以帮助我.我认为这实际上应该是两个相对简单的脚本.我已尝试在某种程度上对我的代码进行评论.

import select
import socket
import sys
import threading
import client

class Server:

#initializing server socket
def __init__(self, event):
    self.host = 'localhost'
    self.port = 50000
    self.backlog = 5
    self.size = 1024
    self.server = None
    self.server_running = False
    self.listen_threads = []
    self.local_threads = []
    self.clients = []
    self.serverSocketLock = None
    self.cmdLock = None
    #here i have also declared some events for the command line input
    #and the receive function respectively, not sure if correct
    self.cmd_event = event
    self.socket_event = event

def openSocket(self):
    #binding server to port
    try: 
        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server.bind((self.host, self.port))
        self.server.listen(5)
        print "Listening to port " + str(self.port) + "..."
    except socket.error, (value,message):
        if self.server:
            self.server.close()
        print "Could not open socket: " + message
        sys.exit(1)

def run(self):
    self.openSocket()

    #making Rlocks for the socket and for the command line input

    self.serverSocketLock = threading.RLock()
    self.cmdLock = threading.RLock()

    #set blocking to non-blocking
    self.server.setblocking(0)
    #making two threads always running on the server,
    #one for the command line input, and one for broadcasting (sending)
    cmd_thread = threading.Thread(target=self.server_cmd)
    broadcast_thread = threading.Thread(target=self.broadcast,args=[self.clients])
    cmd_thread.daemon = True
    broadcast_thread.daemon = True
    #append the threads to thread list
    self.local_threads.append(cmd_thread)
    self.local_threads.append(broadcast_thread)

    cmd_thread.start()
    broadcast_thread.start()


    self.server_running = True
    while self.server_running:

        #connecting to "knocking" clients
        try:
            c = client.Client(self.server.accept())
            self.clients.append(c)
            print "Client " + str(c.address) + " connected"

            #making a thread for each clientn and appending it to client list
            listen_thread = threading.Thread(target=self.listenToClient,args=[c])
            self.listen_threads.append(listen_thread)
            listen_thread.daemon = True
            listen_thread.start()
            #setting event "client has connected"
            self.socket_event.set()

        except socket.error, (value, message):
            continue

    #close threads

    self.server.close()
    print "Closing client threads"
    for c in self.listen_threads:
        c.join()

def listenToClient(self, c):

    while self.server_running:

        #the idea here is to wait until the thread gets the message "client
        #has connected"
        self.socket_event.wait()
        #then clear the event immidiately...
        self.socket_event.clear()
        #and aquire the socket resource
        self.serverSocketLock.acquire()

        #the below is the receive thingy

        try:
            recvd_data = c.client.recv(self.size)
            if recvd_data == "" or recvd_data == "close\n":
                print "Client " + str(c.address) + (" disconnected...")
                self.socket_event.clear()
                self.serverSocketLock.release()
                return

            print recvd_data

            #I put these here to avoid locking the resource if no message 
            #has been received
            self.socket_event.clear()
            self.serverSocketLock.release()
        except socket.error, (value, message):
            continue            

def server_cmd(self):

    #this is a simple command line utility
    while self.server_running:

        #got to have a smart way to make this work

        self.cmd_event.wait()
        self.cmd_event.clear()
        self.cmdLock.acquire()


        cmd = sys.stdin.readline()
        if cmd == "":
            continue
        if cmd == "close\n":
            print "Server shutting down..."
            self.server_running = False

        self.cmdLock.release()


def broadcast(self, clients):
    while self.server_running:

        #this function will broadcast a message received from one
        #client, to all other clients, but i guess any thread
        #aspects applied to the above, will work here also

        try:
            send_data = sys.stdin.readline()
            if send_data == "":
                continue
            else:
                for c in clients:
                    c.client.send(send_data)
            self.serverSocketLock.release()
            self.cmdLock.release()
        except socket.error, (value, message):
            continue

if __name__ == "__main__":
e = threading.Event()
s = Server(e)
s.run()

然后是客户端文件

import select
import socket
import sys
import server
import threading

class Client(threading.Thread):

#initializing client socket

def __init__(self,(client,address)):
    threading.Thread.__init__(self) 
    self.client = client 
    self.address = address
    self.size = 1024
    self.client_running = False
    self.running_threads = []
    self.ClientSocketLock = None

def run(self):

    #connect to server
    self.client.connect(('localhost',50000))

    #making a lock for the socket resource
    self.clientSocketLock = threading.Lock()
    self.client.setblocking(0)
    self.client_running = True

    #making two threads, one for receiving messages from server...
    listen = threading.Thread(target=self.listenToServer)

    #...and one for sending messages to server
    speak = threading.Thread(target=self.speakToServer)

    #not actually sure wat daemon means
    listen.daemon = True
    speak.daemon = True

    #appending the threads to the thread-list
    self.running_threads.append(listen)
    self.running_threads.append(speak)
    listen.start()
    speak.start()

    #this while-loop is just for avoiding the script terminating
    while self.client_running:
        dummy = 1

    #closing the threads if the client goes down
    print "Client operating on its own"
    self.client.close()

    #close threads
    for t in self.running_threads:
        t.join()
    return

#defining "listen"-function
def listenToServer(self):
    while self.client_running:

        #here i acquire the socket to this function, but i realize I also
        #should have a message passing wait()-function or something
        #somewhere
        self.clientSocketLock.acquire()

        try:
            data_recvd = self.client.recv(self.size)
            print data_recvd
        except socket.error, (value,message):
            continue

        #releasing the socket resource
        self.clientSocketLock.release()

#defining "speak"-function, doing much the same as for the above function       
def speakToServer(self):
    while self.client_running:
        self.clientSocketLock.acquire()
        try:
            send_data = sys.stdin.readline()
            if send_data == "close\n":
                print "Disconnecting..."
                self.client_running = False
            else:
                self.client.send(send_data)
        except socket.error, (value,message):
            continue

        self.clientSocketLock.release()

if __name__ == "__main__":
c = Client((socket.socket(socket.AF_INET, socket.SOCK_STREAM),'localhost'))
c.run()

我意识到这是供您阅读的很多代码行,但是正如我所说,我认为其中的概念和脚本应该很容易理解.如果有人可以帮助我以适当的方式同步我的线程,那将是非常有用的.)

预先感谢

-编辑--

好.因此,现在我将代码简化为仅在服务器和客户端模块中都包含发送和接收功能.连接到服务器的客户端拥有自己的线程,两个模块中的发送和接收功能都在各自独立的线程中进行操作.这就像一种魅力,服务器模块中的广播功能将其从一个客户端发送到所有客户端的字符串回显.到目前为止一切顺利!

我想让我的脚本做的下一件事是在客户端模块中采用特定的命令(即关闭")来关闭客户端,并加入线程列表中所有正在运行的线程.我使用事件标志来通知listenToServer和主线程speakToServer线程已读取输入"close".看来主线程跳出了它的while循环,并启动了应该连接其他线程的for循环.但是这里挂了.似乎在设置事件标志时,即使将server_running设置为False,listenToServer线程中的while循环也永远不会停止.

我只在此处发布客户端模块,因为我猜想使这两个线程同步的答案将与同步客户端和服务器模块中的更多线程有关.

import select
import socket
import sys
import server_bygg0203
import threading
from time import sleep

class Client(threading.Thread):

#initializing client socket

def __init__(self,(client,address)):

threading.Thread.__init__(self) 
self.client = client 
self.address = address
self.size = 1024
self.client_running = False
self.running_threads = []
self.ClientSocketLock = None
self.disconnected = threading.Event()

def run(self):

#connect to server
self.client.connect(('localhost',50000))

#self.client.setblocking(0)
self.client_running = True

#making two threads, one for receiving messages from server...
listen = threading.Thread(target=self.listenToServer)

#...and one for sending messages to server
speak = threading.Thread(target=self.speakToServer)

#not actually sure what daemon means
listen.daemon = True
speak.daemon = True

#appending the threads to the thread-list
self.running_threads.append((listen,"listen"))
self.running_threads.append((speak, "speak"))
listen.start()
speak.start()

while self.client_running:

    #check if event is set, and if it is
    #set while statement to false

    if self.disconnected.isSet():
        self.client_running = False 

#closing the threads if the client goes down
print "Client operating on its own"
self.client.shutdown(1)
self.client.close()

#close threads

#the script hangs at the for-loop below, and
#refuses to close the listen-thread (and possibly
#also the speak thread, but it never gets that far)

for t in self.running_threads:
    print "Waiting for " + t[1] + " to close..."
    t[0].join()
self.disconnected.clear()
return

#defining "speak"-function      
def speakToServer(self):

#sends strings to server
while self.client_running:
    try:
        send_data = sys.stdin.readline()
        self.client.send(send_data)

        #I want the "close" command
        #to set an event flag, which is being read by all other threads,
        #and, at the same time set the while statement to false

        if send_data == "close\n":
            print "Disconnecting..."
            self.disconnected.set()
            self.client_running = False
    except socket.error, (value,message):
        continue
return

#defining "listen"-function
def listenToServer(self):

#receives strings from server
while self.client_running:

    #check if event is set, and if it is
    #set while statement to false

    if self.disconnected.isSet():
        self.client_running = False
    try:
        data_recvd = self.client.recv(self.size)
        print data_recvd
    except socket.error, (value,message):
        continue
return

if __name__ == "__main__":
c = Client((socket.socket(socket.AF_INET, socket.SOCK_STREAM),'localhost'))
c.run()

稍后,当我启动并运行该服务器/客户端系统时,我将在实验室中使用的某些电梯型号上使用此系统,每个客户端都收到下达订单或上"和下"呼叫.服务器将运行分配算法,并在最适合所请求订单的客户端上更新电梯队列.我知道这还有很长的路要走,但我想那时候应该只走一步=)

希望有人有时间对此进行研究.预先感谢.

解决方案

我在这段代码中看到的最大问题是,您的工作量太多,无法轻松调试问题.由于逻辑变得非线性,因此线程化会变得极为复杂.尤其是当您不得不担心与锁同步时.

看到客户端相互阻塞的原因是因为您在服务器的listenToClient()循环中使用serverSocketLock的方式.老实说,这不是您的代码现在的问题,但是当我开始对其进行调试并将套接字转换为阻塞套接字时,这成为了问题.如果将每个连接放入其自己的线程中并从中读取,则无需在此处使用全局服务器锁.它们都可以同时从自己的套接字读取,这就是线程的目的.

这是我对您的推荐:

  1. 摆脱一切不必要的锁和多余的线程,从头开始
  2. 让客户端按您的方式进行连接,然后按您的方式将其放入其线程中.只需让他们每秒发送一次数据即可.验证您可以连接和发送多个客户端,并且服务器正在循环和接收.完成这一部分的工作后,您可以继续进行下一部分.
  3. 现在,您已将套接字设置为非阻塞.当数据还没有准备好时,这将导致它们所有人在其循环中真正快速旋转.由于您正在执行线程处理,因此应将其设置为阻塞.然后,读取器线程将只是坐着等待数据并立即响应.

在线程将访问共享资源时使用锁.显然,您随时都需要线程尝试修改服务器属性(例如列表或值).但是当他们在自己的专用套接字上工作时,情况并非如此.

您似乎不需要触发您的读者的事件.您已经收到客户端,然后再启动线程.这样就可以开始了.

简而言之...一次简化并测试一位.工作时,添加更多.现在线程和锁过多.

这是listenToClient方法的简化示例:

def listenToClient(self, c):
    while self.server_running:
        try:
            recvd_data = c.client.recv(self.size)
            print "received:", c, recvd_data
            if recvd_data == "" or recvd_data == "close\n":
                print "Client " + str(c.address) + (" disconnected...")
                return

            print recvd_data

        except socket.error, (value, message):
            if value == 35:
                continue 
            else:
                print "Error:", value, message  

I am currently working on a school project where the assignment, among other things, is to set up a threaded server/client system. Each client in the system is supposed to be assigned its own thread on the server when connecting to it. In addition i would like the server to run other threads, one concerning input from the command line and another concerning broadcasting messages to all clients. However, I can't get this to run as i want to. It seems like the threads are blocking each other. I would like my program to take inputs from the command line, at the "same time" as the server listens to connected clients, and so on.

I am new to python programming and multithreading, and allthough I think my idea is good, I'm not suprised my code doesn't work. Thing is I'm not exactly sure how I'm going to implement the message passing between the different threads. Nor am I sure exactly how to implement the resource lock commands properly. I'm going to post the code for my server file and my client file here, and I hope someone could help me with this. I think this actually should be two relative simple scripts. I have tried to comment on my code as good as possible to some extend.

import select
import socket
import sys
import threading
import client

class Server:

#initializing server socket
def __init__(self, event):
    self.host = 'localhost'
    self.port = 50000
    self.backlog = 5
    self.size = 1024
    self.server = None
    self.server_running = False
    self.listen_threads = []
    self.local_threads = []
    self.clients = []
    self.serverSocketLock = None
    self.cmdLock = None
    #here i have also declared some events for the command line input
    #and the receive function respectively, not sure if correct
    self.cmd_event = event
    self.socket_event = event

def openSocket(self):
    #binding server to port
    try: 
        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server.bind((self.host, self.port))
        self.server.listen(5)
        print "Listening to port " + str(self.port) + "..."
    except socket.error, (value,message):
        if self.server:
            self.server.close()
        print "Could not open socket: " + message
        sys.exit(1)

def run(self):
    self.openSocket()

    #making Rlocks for the socket and for the command line input

    self.serverSocketLock = threading.RLock()
    self.cmdLock = threading.RLock()

    #set blocking to non-blocking
    self.server.setblocking(0)
    #making two threads always running on the server,
    #one for the command line input, and one for broadcasting (sending)
    cmd_thread = threading.Thread(target=self.server_cmd)
    broadcast_thread = threading.Thread(target=self.broadcast,args=[self.clients])
    cmd_thread.daemon = True
    broadcast_thread.daemon = True
    #append the threads to thread list
    self.local_threads.append(cmd_thread)
    self.local_threads.append(broadcast_thread)

    cmd_thread.start()
    broadcast_thread.start()


    self.server_running = True
    while self.server_running:

        #connecting to "knocking" clients
        try:
            c = client.Client(self.server.accept())
            self.clients.append(c)
            print "Client " + str(c.address) + " connected"

            #making a thread for each clientn and appending it to client list
            listen_thread = threading.Thread(target=self.listenToClient,args=[c])
            self.listen_threads.append(listen_thread)
            listen_thread.daemon = True
            listen_thread.start()
            #setting event "client has connected"
            self.socket_event.set()

        except socket.error, (value, message):
            continue

    #close threads

    self.server.close()
    print "Closing client threads"
    for c in self.listen_threads:
        c.join()

def listenToClient(self, c):

    while self.server_running:

        #the idea here is to wait until the thread gets the message "client
        #has connected"
        self.socket_event.wait()
        #then clear the event immidiately...
        self.socket_event.clear()
        #and aquire the socket resource
        self.serverSocketLock.acquire()

        #the below is the receive thingy

        try:
            recvd_data = c.client.recv(self.size)
            if recvd_data == "" or recvd_data == "close\n":
                print "Client " + str(c.address) + (" disconnected...")
                self.socket_event.clear()
                self.serverSocketLock.release()
                return

            print recvd_data

            #I put these here to avoid locking the resource if no message 
            #has been received
            self.socket_event.clear()
            self.serverSocketLock.release()
        except socket.error, (value, message):
            continue            

def server_cmd(self):

    #this is a simple command line utility
    while self.server_running:

        #got to have a smart way to make this work

        self.cmd_event.wait()
        self.cmd_event.clear()
        self.cmdLock.acquire()


        cmd = sys.stdin.readline()
        if cmd == "":
            continue
        if cmd == "close\n":
            print "Server shutting down..."
            self.server_running = False

        self.cmdLock.release()


def broadcast(self, clients):
    while self.server_running:

        #this function will broadcast a message received from one
        #client, to all other clients, but i guess any thread
        #aspects applied to the above, will work here also

        try:
            send_data = sys.stdin.readline()
            if send_data == "":
                continue
            else:
                for c in clients:
                    c.client.send(send_data)
            self.serverSocketLock.release()
            self.cmdLock.release()
        except socket.error, (value, message):
            continue

if __name__ == "__main__":
e = threading.Event()
s = Server(e)
s.run()

And then the client file

import select
import socket
import sys
import server
import threading

class Client(threading.Thread):

#initializing client socket

def __init__(self,(client,address)):
    threading.Thread.__init__(self) 
    self.client = client 
    self.address = address
    self.size = 1024
    self.client_running = False
    self.running_threads = []
    self.ClientSocketLock = None

def run(self):

    #connect to server
    self.client.connect(('localhost',50000))

    #making a lock for the socket resource
    self.clientSocketLock = threading.Lock()
    self.client.setblocking(0)
    self.client_running = True

    #making two threads, one for receiving messages from server...
    listen = threading.Thread(target=self.listenToServer)

    #...and one for sending messages to server
    speak = threading.Thread(target=self.speakToServer)

    #not actually sure wat daemon means
    listen.daemon = True
    speak.daemon = True

    #appending the threads to the thread-list
    self.running_threads.append(listen)
    self.running_threads.append(speak)
    listen.start()
    speak.start()

    #this while-loop is just for avoiding the script terminating
    while self.client_running:
        dummy = 1

    #closing the threads if the client goes down
    print "Client operating on its own"
    self.client.close()

    #close threads
    for t in self.running_threads:
        t.join()
    return

#defining "listen"-function
def listenToServer(self):
    while self.client_running:

        #here i acquire the socket to this function, but i realize I also
        #should have a message passing wait()-function or something
        #somewhere
        self.clientSocketLock.acquire()

        try:
            data_recvd = self.client.recv(self.size)
            print data_recvd
        except socket.error, (value,message):
            continue

        #releasing the socket resource
        self.clientSocketLock.release()

#defining "speak"-function, doing much the same as for the above function       
def speakToServer(self):
    while self.client_running:
        self.clientSocketLock.acquire()
        try:
            send_data = sys.stdin.readline()
            if send_data == "close\n":
                print "Disconnecting..."
                self.client_running = False
            else:
                self.client.send(send_data)
        except socket.error, (value,message):
            continue

        self.clientSocketLock.release()

if __name__ == "__main__":
c = Client((socket.socket(socket.AF_INET, socket.SOCK_STREAM),'localhost'))
c.run()

I realize this is quite a few code lines for you to read through, but as I said, I think the concept and the script in it self should be quite simple to understand. It would be very much appriciated if someone could help me synchronize my threads in a proper way =)

Thanks in advance

---Edit---

OK. So I now have simplified my code to just containing send and receive functions in both the server and the client modules. The clients connecting to the server gets their own threads, and the send and receive functions in both modules operetes in their own separate threads. This works like a charm, with the broadcast function in the server module echoing strings it gets from one client to all clients. So far so good!

The next thing i want my script to do, is taking specific commands, i.e. "close", in the client module to shut down the client, and join all running threads in the thread list. Im using an event flag to notify the listenToServer and the main thread that the speakToServer thread has read the input "close". It seems like the main thread jumps out of its while loop and starts the for loop that is supposed to join the other threads. But here it hangs. It seems like the while loop in the listenToServer thread never stops even though server_running should be set to False when the event flag is set.

I'm posting only the client module here, because I guess an answer to get these two threads to synchronize will relate to synchronizing more threads in both the client and the server module also.

import select
import socket
import sys
import server_bygg0203
import threading
from time import sleep

class Client(threading.Thread):

#initializing client socket

def __init__(self,(client,address)):

threading.Thread.__init__(self) 
self.client = client 
self.address = address
self.size = 1024
self.client_running = False
self.running_threads = []
self.ClientSocketLock = None
self.disconnected = threading.Event()

def run(self):

#connect to server
self.client.connect(('localhost',50000))

#self.client.setblocking(0)
self.client_running = True

#making two threads, one for receiving messages from server...
listen = threading.Thread(target=self.listenToServer)

#...and one for sending messages to server
speak = threading.Thread(target=self.speakToServer)

#not actually sure what daemon means
listen.daemon = True
speak.daemon = True

#appending the threads to the thread-list
self.running_threads.append((listen,"listen"))
self.running_threads.append((speak, "speak"))
listen.start()
speak.start()

while self.client_running:

    #check if event is set, and if it is
    #set while statement to false

    if self.disconnected.isSet():
        self.client_running = False 

#closing the threads if the client goes down
print "Client operating on its own"
self.client.shutdown(1)
self.client.close()

#close threads

#the script hangs at the for-loop below, and
#refuses to close the listen-thread (and possibly
#also the speak thread, but it never gets that far)

for t in self.running_threads:
    print "Waiting for " + t[1] + " to close..."
    t[0].join()
self.disconnected.clear()
return

#defining "speak"-function      
def speakToServer(self):

#sends strings to server
while self.client_running:
    try:
        send_data = sys.stdin.readline()
        self.client.send(send_data)

        #I want the "close" command
        #to set an event flag, which is being read by all other threads,
        #and, at the same time set the while statement to false

        if send_data == "close\n":
            print "Disconnecting..."
            self.disconnected.set()
            self.client_running = False
    except socket.error, (value,message):
        continue
return

#defining "listen"-function
def listenToServer(self):

#receives strings from server
while self.client_running:

    #check if event is set, and if it is
    #set while statement to false

    if self.disconnected.isSet():
        self.client_running = False
    try:
        data_recvd = self.client.recv(self.size)
        print data_recvd
    except socket.error, (value,message):
        continue
return

if __name__ == "__main__":
c = Client((socket.socket(socket.AF_INET, socket.SOCK_STREAM),'localhost'))
c.run()

Later on, when I get this server/client system up and running, I will use this system on some elevator models we have here on the lab, with each client receiving floor orders or "up" and "down" calls. The server will be running an distribution algorithm and updating the elevator queues on the clients that are most appropriate for the requested order. I realize it's a long way to go, but I guess one should just take one step at the time =)

Hope someone has the time to look into this. Thanks in advance.

解决方案

The biggest problem I see with this code is that you have far too much going on right away to easily debug your problem. Threading can get extremely complicated because of how non-linear the logic becomes. Especially when you have to worry about synchronizing with locks.

The reason you are seeing clients blocking on each other is because of the way you are using your serverSocketLock in your listenToClient() loop in the server. To be honest this isn't exactly your problem right now with your code, but it became the problem when I started to debug it and turned the sockets into blocking sockets. If you are putting each connection into its own thread and reading from them, then there is no reason to use a global server lock here. They can all read from their own sockets at the same time, which is the purpose of the thread.

Here is my recommendation to you:

  1. Get rid of all the locks and extra threads that you don't need, and start from the beginning
  2. Have the clients connect as you do, and put them in their thread as you do. And simply have them send data every second. Verify that you can get more than one client connecting and sending, and that your server is looping and receiving. Once you have this part working, you can move on to the next part.
  3. Right now you have your sockets set to non-blocking. This is causing them all to spin really fast over their loops when data is not ready. Since you are threading, you should set them to block. Then the reader threads will simply sit and wait for data and respond immediately.

Locks are used when threads will be accessing shared resources. You obviously need to for any time a thread will try and modify a server attribute like a list or a value. But not when they are working on their own private sockets.

The event you are using to trigger your readers doesn't seem necessary here. You have received the client, and you start the thread afterwards. So it is ready to go.

In a nutshell...simplify and test one bit at a time. When its working, add more. There are too many threads and locks right now.

Here is a simplified example of your listenToClient method:

def listenToClient(self, c):
    while self.server_running:
        try:
            recvd_data = c.client.recv(self.size)
            print "received:", c, recvd_data
            if recvd_data == "" or recvd_data == "close\n":
                print "Client " + str(c.address) + (" disconnected...")
                return

            print recvd_data

        except socket.error, (value, message):
            if value == 35:
                continue 
            else:
                print "Error:", value, message  

这篇关于Python中的线程同步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆