2012-06-23 137 views
1

所以我遇到了一个非常奇怪的错误。我想提出一个基本很少GUI的非常基本的TCP服务器,但是当我产卵的过程中,它会返回以下回溯:Python多处理EOF

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() 

回答

1

PicklingError: Can't pickle 'tkapp' object: <tkapp object at 0x02A4C4F0>它看起来像你可能会试图分享/发送对象的子,虽然含蓄,从根本上multiprocessing模块默认情况下,遵循no share方法,这意味着所有的对象被复制并传送到子进程,以更高性能为代价实现多线程系统更简单更安全的目标。

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似乎被拦截...

1

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

+0

不幸的是,没有工作,我仍然得到相同的错误:( –

2

我得到了同样的问题:

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

我把它改为:

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

我不再收到EOF错误。我不明白这里发生了什么。 太迟了,但希望它能帮助别人。

+1

希望有人可以解释为什么会发生这种情况。 – Athena