我正在编写一个简单的消息传递程序(适用于 2 个用户),该程序可在终端上运行。
为了实现它,我决定创建 2 个进程,一个用于服务器(等待来自其他用户的消息到达),另一个用于客户端(只是将消息发送到其他用户的服务器进程)
事实是,当我运行它时,我收到以下错误:
C:>python message.py
> Process Process-2:
Traceback (most recent call last):
File "C:Python27libmultiprocessingprocess.py", line 258, in_bootstrap
self.run()
File "C:Python27libmultiprocessingprocess.py", line 114, in run
self._target(*self._args, **self._kwargs)
File "C:message.py", line 12, in send_messages
message = raw_input('> ')
EOFError
Process Process-1:
Traceback (most recent call last):
File "C:Python27libmultiprocessingprocess.py", line 258, in
_bootstrap
self.run()
File "C:Python27libmultiprocessingprocess.py", line 114, in run
self._target(*self._args, **self._kwargs)
File "C:message.py", line 25, in receive_messages
message = sc.recv(1024)
error: [Errno 10054] An existing connection was forcibly closed by the
remote host
这是我的蟒蛇代码
from multiprocessing import Process
import socket
direction = "localhost"
global s
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
def send_messages():
s.connect((direction, 5124))
while True:
message = raw_input('> ')
s.send(message)
if message == 'close':
break
print 'Bye'
s.close()
def receive_messages():
s.bind(("localhost",5124))
s.listen(2)
sc, addr = s.accept()
while True:
message = sc.recv(1024)
print message
sc.close()
s.close()
if __name__ == '__main__':
p1 = Process(target = receive_messages)
p1.start()
p2 = Process(target = send_messages)
p2.start()
p1.join()
p2.join()
注1:由于从我的文本编辑器剪切并粘贴到堆栈溢出,可能会出现一些缩进错误。
注2:我正在Windows 10上工作
从文档中:
当心用"类似文件的对象"替换sys.stdin。
多处理最初无条件地称为:
os.close(sys.stdin.fileno())
在
multiprocessing.Process._bootstrap()
方法中 — 这导致了进程中进程的问题。这已更改为:
sys.stdin.close()
sys.stdin = open(os.open(os.devnull, os.O_RDONLY), closefd=False)
这解决了进程相互冲突导致错误文件描述符错误的基本问题,但给应用程序带来了潜在的危险,这些应用程序将
sys.stdin()
替换为具有输出缓冲的"类文件对象"。这种危险是,如果多个进程在此类似文件的对象上调用close()
,则可能导致相同的数据多次刷新到该对象,从而导致损坏。
底线是你的Process
正在关闭stdin
,除非你对它们进行子类化并避免这样做。
您可以考虑使用一个(大写 P)进程来处理通信,然后在原始(小写)进程中执行输入/输出:
if __name__ == '__main__':
p1 = Process(target = receive_messages)
p1.start()
send_messages()
p1.join()
看到这个问题。
当你在 Python 中生成一个线程时,它会关闭 stdin。不能使用子流程来收集标准输入。改用主线程收集输入,并将其从主线程发布到队列。可以将 stdin 传递给另一个线程,但您可能需要在主线程中关闭它。
也许你可以通过使用 fdopen() 在子进程中重新打开 stdin来解决这个问题。看到这个答案。
下面是代码中的一个示例:
from multiprocessing import Process
import socket
import sys
import os
direction = "localhost"
# I got this error
# error: [Errno 106] Transport endpoint is already connected
# when I run your code ,so I made some change
# You can ignore it if everything is ok when your code run
global s1
s1 = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
global s2
s2 = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
def send_messages(fileno):
s1.connect((direction, 5104))
sys.stdin = os.fdopen(fileno) # open stdin in this process
while True:
message = ''
message = raw_input('> ')
s1.send(message)
if message == 'close':
break
print 'Bye'
s1.close()
def receive_messages():
s2.bind(("localhost",5104))
s2.listen(2)
sc, addr = s2.accept()
while True:
message = sc.recv(1024)
if message == 'close':
print 'Bye!'
break
print message
sc.close()
s2.close()
if __name__ == '__main__':
fn = sys.stdin.fileno() # get original file descriptor
p1 = Process(target = receive_messages)
p1.start()
p2 = Process(target = send_messages, args=(fn,))
p2.start()
p1.join()
p2.join()
我测试了它,它有效。
您收到的错误基本上意味着您的raw_input
正在接收空输入。该条件会引发 EOFError,您可以在文档的内置异常部分中阅读有关它的信息。
我以前从未尝试过这样的事情进行多处理,但我想这就是你的问题所在。也许在转向多进程之前,请确保您的逻辑在单个进程中按预期工作,但我仍然觉得尝试启动多个进程以接收用户输入会令人头疼。