Python:线程间同步输入和输出
目前,我正在用Python做一个小项目,想实现一个两人聊天系统。
import socket
import threading
#Callback. Print doesn't work across threads
def data_recieved(data):
print data
#Thread class to gather input
class socket_read(threading.Thread):
sock = object
def __init__(self, sock):
threading.Thread.__init__(self)
self.sock = sock
def run(self):
while True:
data = self.sock.recv(1000)
if (data == "\quitting\\"):
return
data_recieved(self.sock.recv(1000))
####################################################################################
server = False
uname = input("What's your username: ")
print "Now for the technical info..."
port = input("What port do I connect to ['any' if first]: ")
#This is the first client. Let it get an available port
if (port == "any"):
server = True
port = 9999
err = True
while err == True:
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('', port))
err = False
except:
err = True
sock.close()
print "Bound to port #" + str(port)
print "Waiting for client..."
sock.listen(1)
(channel, info) = sock.accept()
else:
#This is the client. Just bind it tho a predisposed port
host = input("What's the IP of the other client: ")
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host, int(port)))
msg = ""
if (server == True):
#Use the connection from accept
reader = socket_read(channel)
else:
#Use the actual socket
reader = socket_read(sock)
reader.start()
while msg != 'quit':
#Get the message...
msg = uname + ": " + input("Message: ")
try:
#And send it
if (server == True):
#Use the connection from accept
channel.send(msg)
else:
#Use direct socket
sock.send(msg)
except:
break
reader.join()
channel.send("\quitting\\")
sock.close()
(我希望这些注释能帮到你)
不过,当我同时请求输入和接收另一个socket的消息时,我遇到了一个小的同步问题。我可以连接,但当我收到消息时,它并没有取消输入的提示。
换句话说,当我收到消息时,它会显示这个
Message: user: I got a message
#Flashing cursor here
所以它并没有取消输入的提示。
而且,我只收到每隔一条消息。
有什么建议吗?
2 个回答
1
好的,抱歉这么快就回答了我自己的问题,但在使用线程时,回调函数真的是太神奇了(至少在Linux的模型上是这样)。
总之,我做了这个:
import socket
import threading
def msg_loop(socket):
msg = ""
if (server == True):
reader = socket_read(channel)
else:
reader = socket_read(sock)
reader.start()
while msg != 'quit':
msg = uname + " said : " + input("Message: ")
print ""
try:
if (server == True):
channel.send('null')
channel.send(msg)
else:
sock.send('null')
sock.send(msg)
except:
break
def data_recieved(data, socket):
print "Hold on...\n\n" + data + "\n"
msg_loop(socket)
class socket_read(threading.Thread):
sock = object
def __init__(self, sock):
threading.Thread.__init__(self)
self.sock = sock
def run(self):
while True:
data = self.sock.recv(1000)
if (data == "\quitting\\" or data == ''):
return
data_recieved(self.sock.recv(1000), self.sock)
####################################################################################
server = False
uname = str(input("What's your username: "))
print "Now for the technical stuff..."
port = input("What port do I connect to ['any' if first]: ")
if (port == "any"):
server = True
port = 9999
err = True
while err == True:
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('', port))
err = False
except:
print "Socket #" + str(port) + " failed"
err = True
sock.close()
port -= 1
print "Bound to port #" + str(port)
print "Waiting for client..."
sock.listen(1)
(channel, info) = sock.accept()
else:
host = input("What's the IP of the other client: ")
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host, int(port)))
if (server == True):
msg_loop(channel)
else:
msg_loop(sock)
reader.join()
channel.send("\quitting\\")
sock.close()
如你所见,我把消息循环作为回调函数加进去了。
另外要注意,我发送了一个空值,以避免“每隔一个”的问题。
还有,我在data_recieved的打印末尾加了一个换行符,以禁用换行。
(如果你喜欢这段代码,它在Windows上运行得不太好。这是因为,显然,Python在Windows上的线程模型执行得没有那么迅速。可以在你本地的Linux机器上试试。)
1
你遇到的问题其实不是同步方面的,而是界面展示的问题。我的建议是,选择一个用户界面工具包(比如 curses、wxPython 或 pyqt)来处理和用户的互动,这样会让你的生活轻松很多。使用 input() 函数虽然在写一些简单的代码时很方便,但它并不够高级。
如果你这样做了,就会发现其实根本不需要使用线程(这通常是个误区),你的问题就会像魔法一样消失!