【问题标题】:Python multiprocessing EOFPython 多处理 EOF
【发布时间】:2012-06-25 09:22:03
【问题描述】:

所以我遇到了一个非常奇怪的错误。我正在为一个 very 基本 TCP 服务器制作一个基本的小 GUI,但是当我生成该进程时,它返回以下回溯:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python27\lib\lib-tk\Tkinter.py", line 1410, in __call__
    return self.func(*args)
  File "C:\Users\username\Desktop\localssh\serverv2.py", line 48, in start_server
    process.start()
  File "C:\Python27\lib\multiprocessing\process.py", line 130, in start
    self._popen = Popen(self)
  File "C:\Python27\lib\multiprocessing\forking.py", line 271, in __init__
    dump(process_obj, to_child, HIGHEST_PROTOCOL)
  File "C:\Python27\lib\multiprocessing\forking.py", line 193, in dump
    ForkingPickler(file, protocol).dump(obj)
  File "C:\Python27\lib\pickle.py", line 224, in dump
    self.save(obj)
  File "C:\Python27\lib\pickle.py", line 331, in save
    self.save_reduce(obj=obj, *rv)
  File "C:\Python27\lib\pickle.py", line 419, in save_reduce
    save(state)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\pickle.py", line 649, in save_dict
    self._batch_setitems(obj.iteritems())
  File "C:\Python27\lib\pickle.py", line 681, in _batch_setitems
    save(v)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\multiprocessing\forking.py", line 66, in dispatcher
    self.save_reduce(obj=obj, *rv)
  File "C:\Python27\lib\pickle.py", line 401, in save_reduce
    save(args)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\pickle.py", line 548, in save_tuple
    save(element)
  File "C:\Python27\lib\pickle.py", line 331, in save
    self.save_reduce(obj=obj, *rv)
  File "C:\Python27\lib\pickle.py", line 419, in save_reduce
    save(state)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\pickle.py", line 649, in save_dict
    self._batch_setitems(obj.iteritems())
  File "C:\Python27\lib\pickle.py", line 681, in _batch_setitems
    save(v)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\pickle.py", line 725, in save_inst
    save(stuff)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\pickle.py", line 649, in save_dict
    self._batch_setitems(obj.iteritems())
  File "C:\Python27\lib\pickle.py", line 681, in _batch_setitems
    save(v)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\pickle.py", line 725, in save_inst
    save(stuff)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\pickle.py", line 649, in save_dict
    self._batch_setitems(obj.iteritems())
  File "C:\Python27\lib\pickle.py", line 681, in _batch_setitems
    save(v)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\pickle.py", line 649, in save_dict
    self._batch_setitems(obj.iteritems())
  File "C:\Python27\lib\pickle.py", line 681, in _batch_setitems
    save(v)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\pickle.py", line 725, in save_inst
    save(stuff)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\pickle.py", line 649, in save_dict
    self._batch_setitems(obj.iteritems())
  File "C:\Python27\lib\pickle.py", line 681, in _batch_setitems
    save(v)
  File "C:\Python27\lib\pickle.py", line 313, in save
    (t.__name__, obj))
PicklingError: Can't pickle 'tkapp' object: <tkapp object at 0x02A4C4F0>

我的代码如下:

import SocketServer
import multiprocessing
from Tkinter import *

class MyTCPHandler(SocketServer.BaseRequestHandler):
    """
    The RequestHandler class for our server.

    It is instantiated once per connection to the server, and must
    override the handle() method to implement communication to the
    client.
    """

    def handle(self):
        # self.request is the TCP socket connected to the client
        self.data = self.request.recv(1024).strip()
        print "{} wrote:".format(self.client_address[0])+str(self.data)
        #print self.data
        # just send back the same data, but upper-cased
        self.request.sendall(self.data.upper())



class Application(object):
    def __init__(self):
        self.root=Tk()
        self.root.resizable(FALSE,FALSE)
        self.root.geometry('500x500')
        self.root.title("Server GUI")
    def set_widgets(self):
        self.start_server_button=Button(self.root,text="Start Server",command=self.start_server)
        self.end_server_button=Button(self.root,text="Stop Server",command=self.stop_server)
        self.logger=Text(self.root,width=50)
    def grid_widgets(self):
        self.start_server_button.grid(row=1,column=0)
        self.end_server_button.grid(row=2,column=0)
        self.logger.grid(row=0,column=0)
    def configure(self):
        pass
    def run(self):
        self.set_widgets()
        self.grid_widgets()
        self.configure()
        self.root.mainloop()
    def start_server(self):
        self.logger.insert(END,"Starting process for client.")
        process=multiprocessing.Process(target=self.start_serving)
        process.start()
    def start_serving(self):
        HOST, PORT = "localhost", 9999
        self.server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
        self.server.serve_forever()
    def stop_server(self):
        self.server.shutdown()
if __name__ == "__main__":
    Application().run()

【问题讨论】:

    标签: python python-2.7 multiprocessing


    【解决方案1】:

    PicklingError: Can't pickle 'tkapp' object: &lt;tkapp object at 0x02A4C4F0&gt; 看起来您可能正在尝试将对象共享/发送到子进程,尽管隐含地,默认情况下基本上是 multiprocessing 模块,遵循 no share 方法,这意味着所有对象都被复制并发送到子进程,目标是更简单、更安全的true 多线程系统,但以性能为代价。

    Python 使用pickle 模块来序列化对象,因此,如果你不能序列化它就不能将它发送到子进程,还有第二个要求,函数必须是可导入的,即:

    def start_server(self):
        self.logger.insert(END,"Starting process for client.")
        process=multiprocessing.Process(target=self.start_serving)
        process.start()
    

    是一个成员函数,它确实是不可导入的,multiprocessing 试图序列化它的所有成员变量,其中大部分无法序列化,尽管这是一种预感。

    你可以试试这个,放在课外。

    def start_serving():
        HOST, PORT = "localhost", 9999
        server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
        server.serve_forever()
    

    假设您不需要任何进程间通信,如果需要,您可以使用多处理模块中的队列。

    这就是您启动子流程的方式。

     def start_server(self):
        self.logger.insert(END,"Starting process for client.")
        self.process = multiprocessing.Process(target=start_serving) # make sure you keep a reference of the process.
        self.process.start()
    

    然后你可以杀死子进程。

    def stop_server(self):
        self.process.terminate()
    
    
    if __name__ == "__main__":
        Application().run()
    

    虽然我建议您使用ThreadingMixIn 而不是手动创建子进程,但我不确定它是使用thread 还是process,因为thread 实际上并没有在多核机器上运行,因为GIL 同时处理。 我已经测试过了,不幸的是你无法杀死子进程,serve_forever 似乎正在阻塞...

    【讨论】:

      【解决方案2】:

      我不完全确定这是否能解决您的问题,但是,another stackoverflow question 可能有您正在寻找的答案。看来您需要将__getstate__() 方法添加到Application 类中。

      【讨论】:

      • 不幸的是这不起作用,我仍然得到同样的错误:(
      【解决方案3】:

      我遇到了同样的问题:

      p=multiprocessing.Process(target=self.targetMethod)
      

      我改成了:

      p=multiprocessing.Process(target=self.targetMethod())
      

      我不再收到 EOF 错误。我不明白这里到底发生了什么。 为时已晚,但希望它对某人有所帮助。

      【讨论】:

      • 希望有人能解释为什么会这样。
      • 这将在当前进程中运行targetMethod并将结果分配给target。如果返回值为None,我希望这不会在子进程中运行任何东西。
      猜你喜欢
      • 1970-01-01
      • 2019-09-21
      • 1970-01-01
      • 2011-04-20
      • 2016-05-30
      • 1970-01-01
      相关资源
      最近更新 更多