这个多处理 python 脚本有什么问题?



我正在编写一个简单的消息传递程序(适用于 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,您可以在文档的内置异常部分中阅读有关它的信息。

我以前从未尝试过这样的事情进行多处理,但我想这就是你的问题所在。也许在转向多进程之前,请确保您的逻辑在单个进程中按预期工作,但我仍然觉得尝试启动多个进程以接收用户输入会令人头疼。

相关内容

  • 没有找到相关文章

最新更新