簡體   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