Python优雅地终止多处理和gui处理

时间:2013-07-13 15:35:53

标签: python multiprocessing glade

我使用glade作为我的gui并创建一个运行我的gui的进程。当点击'on'时,这个应用程序将打开一个套接字。当我按“发送”时,它会将文本字段中的任何内容发送到套接字。套接字接收此数据并将其发回。问题是我将数据发送到套接字之后线程没有终止。在我关闭我的gui之后它调用了一个sys.exit()但是也留下了一个进程并且没有终止。我相信错误在于我如何实现我的流程或一般的所有处理。任何人都可以对此有所启发吗?它也与我上一篇文章有​​关。感谢

main.py

//为我的gui创建新进程并显示它的主线程

import socket, thread, gtk, Handler, sys, os, multiprocessing 
sys.setrecursionlimit(10000)  


if __name__ == '__main__':

    builder = gtk.Builder()
    #32bit template.glade 64bit template-2.22
    # @todo add switching between architectures
    #
    builder.add_from_file("template/template-2.22.glade")
    builder.connect_signals(Handler.Handler(builder))
    window = builder.get_object("window1")
    window.show_all()
    try:
        p =  multiprocessing.Process(target=gtk.main())
        p.start()

    except:
            print "Error Starting new Thread"

handler.py

//用于gtk glade信号的处理程序,创建新线程并处理按钮和填充

import thread, threading, os, server, client,multiprocessing, time
import sys, gtk


class Handler(object):
    '''
    classdocs
    '''
    myobject = ''

    def __init__(self,object1):
        #Getting glade builder
        self.myobject = object1
        '''
        Constructor
        '''

    def clickme(self,value):

        myserver = server.Server()
        try:
            p =  multiprocessing.Process(target=myserver.run)
            p.start()

        except:
            pass

    def sendmessage(self,value):
        text = self.myobject.get_object('entry1').get_text()
        print text
        msg = client.MyClass()
        p =  multiprocessing.Process(target=msg.run,args=([text]))
        p.start()

server.py

//打开套接字并侦听传入的数据并将其发回

import socket,multiprocessing, gtk, sys

class Server:
    '''
    classdocs
    '''
    def __init__(self):
        '''
        Constructor
        '''

    def run(self):

        try:
            while 1:
                HOST = 'localhost'                 # Symbolic name meaning the local host
                PORT = 50006              # Arbitrary non-privileged port
                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
                s.bind((HOST, PORT))
                s.listen(5)
                conn, addr = s.accept()
                print 'Connected by', addr
                while True:
                    data = conn.recv(1024)
                    if not data:
                        conn.close()
                        sys.exit()
                        break
                    elif data != '':
                        conn.sendall(data)
                        break

            print "Closing"    
            #conn.close()
        finally:
            print "End"
            pass

client.py

//将文本区域内的任何内容发送到套接字

import time

class MyClass:
    '''
    classdocs
    '''

    def __init__(self):
        '''
        Constructor
        '''
    def run(self,text):
        try:
            import socket
            HOST = 'localhost'    # The localhost
            PORT = 50006             # The same port as used by the server
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.connect((HOST, PORT))
            s.send(text)
            data = s.recv(1024)

            while 1:
                if data != '':
                    print 'Received', repr(data)
                    break
        finally:
            pass

1 个答案:

答案 0 :(得分:0)

这是错的:

p =  multiprocessing.Process(target=gtk.main())
p.start()

首先,你不能在子进程中启动gtk主循环,即使你做得很好。幸运的是,当调用 main时,该过程永远不会真正尝试启动gtk.main(),这将阻塞直到主循环退出然后返回None。所以你实际做的是:

gtk.main()
p =  multiprocessing.Process(target=None)
p.start()

通过代码的其余部分,您不断创建新流程,然后忘记它们。如果你要保留对它们的引用,你至少可以尝试向它们发送TERM信号以关闭它们(使用Process.terminate,或设置daemon标志)。如果要干净地关闭子进程,则需要在子进程中handle that signal,或使用其他IPC机制使其完全关闭(如mutliprocessing.Event,...)。

然后有这个:

            while True:
                data = conn.recv(1024)
                if not data:
                    conn.close()
                    sys.exit()
                    break
                elif data != '':
                    conn.sendall(data)
                    break

这个while循环永远不会循环(除非recv神奇地返回别的东西然后是一个字符串)。第一个执行路径以sys.exit()结束(整个服务器关闭 - 中断无法访问),第二个以break结束,因此循环无用。

以下几行恰恰相反:

        data = s.recv(1024)
        while 1:
            if data != '':
                print 'Received', repr(data)
                break

除非第一行中data'',否则这将是无限循环,因为data的值不会再改变。

一般来说,大多数情况下你并不需要多处理。如果必须做很多工作,那么在不同的进程中启动服务器可能没问题,但是为了发送一些数据而发布子进程是过度的。使用套接字发送和接收是IO绑定的,这里使用线程会更合理。

您有两个类(ServerHandler),它们只有两个方法,其中一个是__init__,另一个只用作子进程的目标:< / p>

    myserver = server.Server()
    try:
        p =  multiprocessing.Process(target=myserver.run)

    msg = client.MyClass()
    p =  multiprocessing.Process(target=msg.run,args=([text]))

这表明这些不应该是课程而是功能。