Python多处理EOF

时间:2012-06-23 05:03:11

标签: python python-2.7 multiprocessing

所以我遇到了一个非常奇怪的错误。我正在为非常基本的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()

3 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

PicklingError: Can't pickle 'tkapp' object: <tkapp object at 0x02A4C4F0>看起来您可能正在尝试共享/发送对象到子进程,但默认情况下,默认情况下,基本上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()

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

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

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而不是手动创建子流程,但我不确定它是否使用threadprocess thread实际上并不由于GIL而在进程中运行多核计算机。 我测试了它,不幸的是你不能杀掉子进程,serve_forever似乎阻塞了......

答案 2 :(得分:1)

我遇到了同样的问题:

RewriteCond %{QUERY_STRING}     ^debug=1$     [NC]
RewriteRule    (.*) app/webroot/$1 [L]

我把它改为:

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

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