1

だから私は非常に奇妙なエラーに遭遇しています。非常に基本的な 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()
4

3 に答える 3

1

PicklingError: Can't pickle 'tkapp' object: <tkapp object at 0x02A4C4F0>オブジェクトをサブプロセスに共有/送信しようとしているように見えますが、暗黙的に、基本的にmultiprocessingデフォルトのモジュールはno share方法論に従います。つまり、すべてのオブジェクトがコピーされてサブプロセスに送信され、はるかに簡単でtrueとりわけパフォーマンスを犠牲にして、より安全なマルチスレッドシステム。

Pythonはpickleモジュールを使用してオブジェクトをシリアル化するため、シリアル化できない場合はサブプロセスに送信できません。2つ目の要件があります。関数はインポート可能である必要があり、次のようになります。

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サブプロセスを手動で作成する代わりに使用することをお勧めしますが、プロセスの実行中にGILが原因で、マルチコアマシンで実際に実行されるのか、実行されないのthreadprocessがわかりません。thread私はそれをテストしました、残念ながらあなたはサブプロセスを殺すことができません、serve_foreverブロックしているようです...

于 2012-06-23T05:22:26.590 に答える
1

これで問題が解決するかどうかは完全にはわかりませんが、別のスタックオーバーフローの質問にあなたが探している答えがあるかもしれません. __getstate__()メソッドをApplicationクラスに追加する必要があるようです。

于 2012-06-23T05:14:09.247 に答える