Programm doppelt öffnen verhindern

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
pSy
User
Beiträge: 44
Registriert: Montag 4. Oktober 2004, 17:58
Kontaktdaten:

ist ja wirklich n tolles modul... aber wie benutze ich die funktion DoConnect, ohne das sich das Script ewig daran aufhält?

Wenn ich

Code: Alles auswählen

servermodul.DoConnect('myCoolScript')
benutze, hängt das Programm an dieser Stelle fest.

Gruß
pSy
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hi pSy,

wie ich das sehe, musst du der Funktion DoConnect noch deine Main-Funktion als Parameter mitgeben, Diese wird dann ausgeführt.


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
HarryH
User
Beiträge: 266
Registriert: Freitag 23. Mai 2003, 09:08
Wohnort: Deutschland

Hallo zusammen

Ich habe das Modul nocht etwas ausdokumentiert und eine Kleinigkeit verbessert.

Code: Alles auswählen

# -*- coding: iso-8859-1 -*-

import socket
import sys
import threading

#Socket- und Portspeicher
_sock=[None]
_port=[None]

#Verbinden
def DoConnect(progName, funktion=None, parameter=None):
    """
    progname =      The identified name for the programm which connect you. Must be a name,
                    that will really differ beetwen programs.
    funktion =      The funktion which will be started, when the programm will double opened
    parameter =     The parameter for the funktion
    """
    if not progName or type(progName) != str:
        raise ValueError, 'Value must be a string and may be not empty'
    HOST = "localhost"
    for newport in xrange(65000, 65536):
        if not _port[0]:
            port = newport
        else:
            port = _port[0]
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.bind((HOST, port))
            s.listen(1)
            _sock[0] = s
            _port[0] = port
            #start serverthread
            serv = Miniserver(s, progName, port, funktion, parameter)
            serv.start()
            print "Port %s gestartet"% port
            break
        except:
            try:
                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                s.connect((HOST, port))
                s.send(progName)
                data=s.recv(1024)
                s.close()
                if data != progName and progName != "!%END%!":
                    continue
                else:
                    return "LOCK"
            except:
                continue


#Verbindung trennen
def DoDisconnect():
    """ Break up the connected socket"""
    DoConnect("!%END%!")

#Server
class Miniserver(threading.Thread):
    def __init__(self, sock, progName, port, funktion, parameter):
        """
        sock =          The new socket
        progname =      The identified name for the programm which connect you. Must be a name,
                        that will really differ beetwen programs.
        port =          The reserved port for the socket
        funktion =      The funktion which will be started, when the programm will double opened
        parameter =     The parameter for the funktion

        """
        threading.Thread.__init__(self)
        self.s = sock
        self.progName= progName
        self.port= port
        self.funktion = funktion
        self.parameter = parameter

    def run(self):
        """Let run the thread to observe the started programs"""
        while 1:
            client, addr = self.s.accept()
            port = client.getsockname()[1]
            client.send(self.progName)
            progName = client.recv(1024)
            client.close()
            if self.port == port and self.progName != progName and progName != "!%END%!":
                continue
            if self.port == port and progName == "!%END%!":
                print "Port %s beendet"% port
                break
            if self.port == port and self.funktion:
                self.funktion(self.parameter)
                print "Übergebene Funktion des Ports %s wurde gestartet"% port

if __name__ == "__main__":
    pass
Gestartet wird mit:

Code: Alles auswählen

server=modul.DoConnect("Programmname")
if server == "LOCK":
      sys.exit()
Beendet wir mit:

Code: Alles auswählen

modul.DoDisconnect()
Wird eine Funktion mit übergeben wird folgendermaßen gestartet:

Code: Alles auswählen

server=modul.DoConnect("Programmname", funktion, parameter)
if server == "LOCK":
      sys.exit()
Beendet wird genauso wie oben.

Der Sinn dieses Moduls ist, das doppelt öffnen von Programmen zu verhindern. Wird ein Programm doppelt geöffnet, gibt das Modul "LOCK" zurück. Das kann man dann auswerten.
Zusätzlich erhält man die Möglichkeit bei doppelten Aufruf eine Funktion ausführen zu lassen. Funktion und Parameter sind aber nicht unbedingt erforderlich.
Gruß, Harry
Gast

danke... du bist zu gut zu uns :lol:
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo zusammen

Bin heute auf diesen Thread gestoßen und habe den Code von HarryH, laut meinen Fehlermeldungen angepasst.
So läuft dieser bei mir bisher problemlos.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# For Python3.x

import sys
import socket
import threading

# Socket- und Portspeicher
_sock=[None]
_port=[None]

# Verbinden
def DoConnect(progName, funktion=None, parameter=None):
    """
    progname =      The identified name for the programm which connect you. Must be a name,
                    that will really differ beetwen programs.
    funktion =      The funktion which will be started, when the programm will double opened
    parameter =     The parameter for the funktion
    """
    if not progName or type(progName) != str:
        raise ValueError (e, 'Value must be a string and may be not empty')
    HOST = "localhost"
    for newport in range(65000, 65536):
        if not _port[0]:
            port = newport
        else:
            port = _port[0]
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.bind((HOST, port))
            s.listen(1)
            _sock[0] = s
            _port[0] = port
            # start serverthread
            serv = Miniserver(s, progName, port, funktion, parameter)
            serv.start()
            print('Port %s gestartet' % port)
            break
        except:
            try:
                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                try:
                    s.connect((HOST, port))
                except socket.error:
                    return
                s.send(progName)
                data=s.recv(1024)
                s.close()
                print(progName, data)
                if data != progName and progName != "!%END%!":
                    continue
                else:
                    return "LOCK"
            except TypeError:
                return "LOCK"


# Verbindung trennen
def DoDisconnect():
    """ Break up the connected socket"""
    DoConnect("!%END%!")

# Server
class Miniserver(threading.Thread):
    def __init__(self, sock, progName, port, funktion, parameter):
        """
        sock =          The new socket
        progname =      The identified name for the programm which connect you. Must be a name,
                        that will really differ beetwen programs.
        port =          The reserved port for the socket
        funktion =      The funktion which will be started, when the programm will double opened
        parameter =     The parameter for the funktion

        """
        threading.Thread.__init__(self)
        self.s = sock
        self.progName = progName
        self.port = port
        self.funktion = funktion
        self.parameter = parameter

    def run(self):
        """Let run the thread to observe the started programs"""
        while 1:
            client, addr = self.s.accept()
            port = client.getsockname()[1]
            try:
                client.send(self.progName)
            except TypeError:
                break
            progName = client.recv(1024)
            client.close()
            if self.port == port and self.progName != progName and progName != "!%END%!":
                continue
            if self.port == port and progName == "!%END%!":
                print('Port %s beendet' % port)
                break
            if self.port == port and self.funktion:
                self.funktion(self.parameter)
                print('Übergebene Funktion des Ports %s wurde gestartet' % port)

if __name__ == "__main__":
    pass
In dem zu startenden Programm, habe das am Anfang des Programmes so eingebunden:

Code: Alles auswählen

# Kontrollfunktion gegen doppeltes Starten des Programmes
import gui_sock_control as modul

gui_work = os.path.join(os.path.dirname(__file__), 'gui_work.py')

server = modul.DoConnect(gui_work)
if server == "LOCK":
      sys.exit()
Was mich interessiert:
Wie kann ich sicherstellen , daß wenn mein Programm mit dem X-Button am Fenster beendet wird, daß

Code: Alles auswählen

modul.DoConnect()
ausgeführt wird?

Grüße Nobuddy
HarryH
User
Beiträge: 266
Registriert: Freitag 23. Mai 2003, 09:08
Wohnort: Deutschland

So z.B.:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# For Python3.x

import sys
import socket
import threading
import atexit

# Socket- und Portspeicher
_sock=[None]
_port=[None]

# Exit abfangen
def OnClose(port):
    if port == _port[0]:
        DoDisconnect()

# Verbinden
def DoConnect(progName, funktion=None, parameter=None):
    """
    progname =      The identified name for the programm which connect you. Must be a name,
                    that will really differ beetwen programs.
    funktion =      The funktion which will be started, when the programm will double opened
    parameter =     The parameter for the funktion
    """
    if not progName or type(progName) != str:
        raise ValueError (e, 'Value must be a string and may be not empty')
    HOST = "localhost"
    for newport in range(65000, 65536):
        if not _port[0]:
            port = newport
        else:
            port = _port[0]
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.bind((HOST, port))
            s.listen(1)
            _sock[0] = s
            _port[0] = port
            # start serverthread
            serv = Miniserver(s, progName, port, funktion, parameter)
            serv.start()            
            atexit.register(OnClose, port)
            print('Port %s gestartet' % port)
            break
        except:
            try:
                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                try:
                    s.connect((HOST, port))
                except socket.error:
                    return
                s.send(progName)
                data=s.recv(1024)
                s.close()
                print(progName, data)
                if data != progName and progName != "!%END%!":
                    continue
                else:
                    return "LOCK"
            except TypeError:
                return "LOCK"


# Verbindung trennen
def DoDisconnect():
    """ Break up the connected socket"""
    DoConnect("!%END%!")

# Server
class Miniserver(threading.Thread):
    def __init__(self, sock, progName, port, funktion, parameter):
        """
        sock =          The new socket
        progname =      The identified name for the programm which connect you. Must be a name,
                        that will really differ beetwen programs.
        port =          The reserved port for the socket
        funktion =      The funktion which will be started, when the programm will double opened
        parameter =     The parameter for the funktion

        """
        threading.Thread.__init__(self)
        self.s = sock
        self.progName = progName
        self.port = port
        self.funktion = funktion
        self.parameter = parameter

    def run(self):
        """Let run the thread to observe the started programs"""
        while 1:
            client, addr = self.s.accept()
            port = client.getsockname()[1]
            try:
                client.send(self.progName)
            except TypeError:
                break
            progName = client.recv(1024)
            client.close()
            if self.port == port and self.progName != progName and progName != "!%END%!":
                continue
            if self.port == port and progName == "!%END%!":
                print('Port %s beendet' % port)
                break
            if self.port == port and self.funktion:
                self.funktion(self.parameter)
                print('Übergebene Funktion des Ports %s wurde gestartet' % port)

if __name__ == "__main__":
    pass
Gruß, Harry
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo HarryH

Danke für Deine schnelle Antwort! :wink:

Der neu hinzugefügte Code, funktioniert bei mir aber nicht.
Nach einigem Herumtesten, ist ein Doppelstart so trotzdem möglich.

Ich dachte eigentlich das direkte Abfangen des Programmendes in dem gestarteten Programm selbst.
Mein Programm beinhaltet eine grafische Oberfläche (Tkinter).
Dort besteht die Möglichkeit, mit einem Beenden-Button sowie auch dem X-Button das Programm zu beenden.

Sinn Deines Programmes, ist ja für das Starten mehrere verschiedener Python-Programme gedacht, wenn ich das richtig verstanden habe.
Ich habe mir gedacht, den beim Programmstart erhaltenen Port, beim Programmende wieder an dein Programm zurück zu übergeben, damit dann 'progName' und der dazugehörige Port wieder freigegeben werden.

Wünsche schöne Weihnachten
Nobuddy

Nachtrag:
Sorry, funktioniert alles! :wink:
Hatte zuvor 'OnClose(port)' in meinem Programm nicht integriert gehabt.
Eine Frage bleibt noch.
Wie kann ich das abfangen, wenn man mit dem X-Button das Programm zu beendet?
HarryH
User
Beiträge: 266
Registriert: Freitag 23. Mai 2003, 09:08
Wohnort: Deutschland

Hi,

In den python manuals wird schön beschrieben unter welchen Umständen das modul "atexit" funktioniert und unter welchen nicht.
Note: the functions registered via this module are not called when the program is killed by a signal not handled by Python, when a Python fatal internal error is detected, or when os._exit() is called.
Habe mit Tkinter kaum Erfahrungen; arbeite mit wxPython. Dort ist es wichtig das Close-Event anzufangen und das Programm dann mit sys.exit() zu beenden. Dann werden auch die in atexit.register(...) registrierten Funktionen gestartet.
Gruß, Harry
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hallo HarryH

Danke für Deine Info, werde mal im Tkinter-Forum nachfragen.
Dein Programm funktioniert prima! :wink:

Grüße Nobuddy
Antworten