繁体   English   中英

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

[英]Python terminate multiprocessing and gui process gracefully

我使用林间空地作为我的GUI,并创建了一个运行我的GUI的进程。单击“打开”时,此应用程序将打开一个套接字。 当我按“发送”时,它将文本字段中的所有内容发送到套接字。 套接字接收此数据并将其发送回。 问题是我将数据发送到套接字后,线程没有终止。 另外,在我关闭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

这是错误的:

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

首先,即使您严格执行gtk主循环,也无法在子进程中启动它。 幸运的是,当您调用 gtk.main() ,该过程从未真正尝试启动main ,它会阻塞直到main循环退出,然后返回None 因此,您实际上正在做的是:

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

遍历其余的代码,您将继续创建新流程,然后忘记它们。 如果要保留对它们的引用,则至少可以尝试向它们发送TERM信号以将其关闭(使用Process.terminate或设置daemon标志)。 如果要完全关闭子进程,则需要处理该子mutliprocessing.Event 中的信号 ,或者使用其他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__ ,另一种仅用作子流程的目标:

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

和:

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

这表明它们不应该是类而是函数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM