【问题标题】:Python terminate multiprocessing and gui process gracefullyPython优雅地终止多处理和gui进程
【发布时间】:2013-07-13 15:35:53
【问题描述】:

我正在使用 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

【问题讨论】:

    标签: python multiprocessing glade


    【解决方案1】:

    这是错误的:

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

    首先,您不能在子进程中启动 gtk 主循环,即使您这样做是正确的。幸运的是,当您调用 gtk.main() 时,该进程从未真正尝试启动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 的值不会再改变。

    一般来说,您实际上并不需要多处理。如果必须做很多工作,在不同的进程中启动服务器可能没问题,但是为了发送一些数据而生成一个子进程是过大的。使用socket发送和接收是IO绑定的,这里使用线程会更合理。

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

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

    和:

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

    这表明这些不应该是类,而是函数。

    【讨论】:

      猜你喜欢
      • 2022-06-30
      • 1970-01-01
      • 2011-01-04
      • 1970-01-01
      • 1970-01-01
      • 2019-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多