Hallo,
Ich möchte verhindern das ein Programm dopppelt geöffnet werden kann, wenn es bereits läuft. Ich arbeite auf Windows. Hat jemand eine Idee
Weiter möchte ich , falls das Programm bereits läuft, in dieses eingreifen können. Das heißt eine Funktion in diesem aufrufen.
Könnt ihr mir bitte weiterhelfen.
Programm doppelt öffnen verhindern
Ich denke in beiden Fällen sind Sockets die richtige Lösung. Binde einfach beim Programmstart Dein Programm an einen TCP-Port. Wenn dann die zweite Instanz startet, kannst Du das abfangen, und mit einer Fehlermeldung beenden. Für zweiteres kannst Du auch Sockets sehr gut benutzen, einfach Kommunikation via TCP.
HTH
fs111
HTH
fs111
Pydoc-Integration in vim - Feedback willkommen: http://www.vim.org/scripts/script.php?script_id=910
Hallo fs111,
Danke für deine sehr schnelle Antwort. Ich habe leider überhaupt keine Ahnung von Sockets. Ich weiss nicht mal was damit gemeint ist. Könntest du mir das bitte ein wenig erklären und mir vielleicht ein Beispiel für die Lösung meines Problems zeigen.
Das wäre super. Danke
Danke für deine sehr schnelle Antwort. Ich habe leider überhaupt keine Ahnung von Sockets. Ich weiss nicht mal was damit gemeint ist. Könntest du mir das bitte ein wenig erklären und mir vielleicht ein Beispiel für die Lösung meines Problems zeigen.
Das wäre super. Danke
Gruß, Harry
-
- User
- Beiträge: 34
- Registriert: Samstag 24. Juli 2004, 19:25
- Kontaktdaten:
unter windows macht man das eigentlich mit DDE ... geht auch recht einfach.
bei win32all ist ein beispiel für DDE server und client dabei....
sockets wären natürlich OS unabhängiger
bei win32all ist ein beispiel für DDE server und client dabei....
sockets wären natürlich OS unabhängiger
Sockets sind die Endpunkte der Datenübertragung bei Netzwerkkommunikation (Unix-Domain-Sockets lasse ich mal außen vor) via TCP und UDP, also die Technik, die es Dir ermöglichen über Netwerke hinweg zu kommunizieren. Genauso wie Dein Browser und der Server dieses Forums es tun. Die beiden Protokolle, die dafür in zuständig sind, sind TCP (Transmission Control Protocol) und UDP (User Datagram Protocol), welche beide über Sockets kommunizieren (dafür braucht man auch die Port-Nummern). Du solltest hierbei TCP verwenden, da es eine zuverlässige Datenübertragung bereit stellt (reliable). Du würdest für das Locking einfach einen Socket an einer bestimmten Portnummmer öffnen (am besten möglichst hoch), und damit wäre schon alles getan, da immer nur ein Dienst/Programm einen Portnummer zur gleichen Zeit belegen kann, würde die zweite Instanz den Socket nicht öffnen können, und genau dieses könntest Du abfangen. Da Du ja nun schon eine Applikation hast, die auf Anfrage wartet, kannst Du darum noch ein Commando-Interface basteln, welches Kommandos von einem Client, der sich zur Anwendung verbindet entgegen nimmt.
Da ich jetzt nicht weiß, wie bewandert Du mit Netwerken, TCP/IP etc bist, kann ich hier auch noch sehr viel mehr schreiben, oder Du sagst, wo Du dann Probleme hast.
Als Python-Einstieg: http://www.amk.ca/python/howto/sockets/
und falls Du noch Links zu TCP/IP-Themen brauchst, sag einfach Bescheid.
fs111
Da ich jetzt nicht weiß, wie bewandert Du mit Netwerken, TCP/IP etc bist, kann ich hier auch noch sehr viel mehr schreiben, oder Du sagst, wo Du dann Probleme hast.
Als Python-Einstieg: http://www.amk.ca/python/howto/sockets/
und falls Du noch Links zu TCP/IP-Themen brauchst, sag einfach Bescheid.
fs111
Pydoc-Integration in vim - Feedback willkommen: http://www.vim.org/scripts/script.php?script_id=910
-
- Python-Forum Veteran
- Beiträge: 2010
- Registriert: Freitag 11. Oktober 2002, 18:00
- Wohnort: Salzburg
- Kontaktdaten:
Hallo zusammen,
warum mit Kanonen auf Spatzen schießen?
Erstell doch beim Programmstart einfach eine Datei, die beim Programmende wieder gelöscht wird. Unter windows gibts ja sicher auch ein C:\\tmp Verzeichnis oder so wo das einfach möglich ist. Bevor die Datei beim Programmstart erstellt wird einfach testen ob sie schon existiert, dann läuft das Programm schon und es kann eine entsprechende Meldung ausgegeben werden.
Gruß
Dookie
warum mit Kanonen auf Spatzen schießen?
Erstell doch beim Programmstart einfach eine Datei, die beim Programmende wieder gelöscht wird. Unter windows gibts ja sicher auch ein C:\\tmp Verzeichnis oder so wo das einfach möglich ist. Bevor die Datei beim Programmstart erstellt wird einfach testen ob sie schon existiert, dann läuft das Programm schon und es kann eine entsprechende Meldung ausgegeben werden.
Code: Alles auswählen
import os, sys
def main():
pass # hier ist das Hauptprogramm
tmplockname = "C:\\tmp\testprog.lock"
if os.path.exists(tmplockname):
print "Testprog läuft schon"
sys.exit()
f = file(tmplockname,'w')
f.write(" ")
f.close()
main()
os.remove(tmplockname)
Gruß
Dookie
[code]#!/usr/bin/env python
import this[/code]
import this[/code]
Hi. So kann aber keine Funktion im anderem Programm gerufen werden... Ich würde das mit den Sockets auch so handhaben, da dann beim gewaltsamen Abschuss des Programmes auch der Port wieder geschlossen wird. Die Datei würde weiter bestehen bleiben...
Hallo,
Schon mal vielen Dank für alle eure Gedanken.
Ich werde die von fs111 empfohlene Doku zur Socketprogrammierung mal unter die Lupe nehmen. Das ist genau das was ich brauche. Ich werde mich wieder rühren wenn ich Probleme damit habe.
Schon mal vielen Dank für alle eure Gedanken.
Ich werde die von fs111 empfohlene Doku zur Socketprogrammierung mal unter die Lupe nehmen. Das ist genau das was ich brauche. Ich werde mich wieder rühren wenn ich Probleme damit habe.
Gruß, Harry
Hallo,
Ich habe folgendes ausprobiert:
Diesen Code habe ich am Anfang meines Programms gehängt. Starte ich es doppelt, bricht er wie erwünscht ab. Gut so.
Nun habe ich gleichen Code in ein Modul geschrieben und dieses Modul dann am Anfang meines Programms gestartet. Dann bricht er nicht wie gewünscht ab. Warum?
Ich habe folgendes ausprobiert:
Code: Alles auswählen
try:
HOST = '' # Symbolic name meaning the local host
PORT = 1234567890 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
except:
sys.exit()
Nun habe ich gleichen Code in ein Modul geschrieben und dieses Modul dann am Anfang meines Programms gestartet. Dann bricht er nicht wie gewünscht ab. Warum?
Gruß, Harry
Die Portnummer ist viel zu groß! TCP und UDP-Ports gehen von 1-65536, die von Dir angegebenen Zahl sprengt alle Grenzen, ich wundere mich, dass es überhaupt funktioniert hat...
Hier mal ein paar Hintergründe zu TCP/IP:
http://www.rvs.uni-bielefeld.de/~heiko/ ... nhalt.html
http://de.wikipedia.org/wiki/TCP/IP-Referenzmodell
http://de.wikipedia.org/wiki/TCP
http://www.redbooks.ibm.com/pubs/pdfs/r ... 243376.pdf
fs111
Hier mal ein paar Hintergründe zu TCP/IP:
http://www.rvs.uni-bielefeld.de/~heiko/ ... nhalt.html
http://de.wikipedia.org/wiki/TCP/IP-Referenzmodell
http://de.wikipedia.org/wiki/TCP
http://www.redbooks.ibm.com/pubs/pdfs/r ... 243376.pdf
fs111
Pydoc-Integration in vim - Feedback willkommen: http://www.vim.org/scripts/script.php?script_id=910
Hallo,
Ich habe es auch mit einem innerhalb des Bereichs liegenden Wert versucht (65007 - so wie in der Python-Doku). Der gewünschte Erfolg bleibt jedoch aus, sobald ich über ein Modul arbeite.
Das Modul sieht so aus:
Ich rufe das Modul aus meinem Hauptprogramm auf und starte die Funktion 'DoConnect'.
Ich habe es auch mit einem innerhalb des Bereichs liegenden Wert versucht (65007 - so wie in der Python-Doku). Der gewünschte Erfolg bleibt jedoch aus, sobald ich über ein Modul arbeite.
Das Modul sieht so aus:
Code: Alles auswählen
# -*- coding: iso-8859-1 -*-
import socket
import sys
def DoConnect():
try:
HOST = '' # Symbolic name meaning the local host
PORT = 65007 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
except:
sys.exit()
Gruß, Harry
Hi. Wahrscheinlich wird der Socket sofort wieder gelöscht, da er ja nur in einer Funktion ohne Rückgabe steht. Probier mal das hier:
Code: Alles auswählen
# -*- coding: iso-8859-1 -*-
import socket
import sys
_sock=[None]
def DoConnect():
try:
HOST = '' # Symbolic name meaning the local host
PORT = 65007 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
_sock[0]=s
except:
sys.exit()
Hi,
Ja, super, es geht!
Aber ich verstehe noch nicht so genau was da passiert. könntest su mir das bitte erklären
Jetzt muss ich es nur noch schaffen in dem Hauptprogramm eine Funktion aufzurufen. Könntest du mir dabei bitte auch einen Lösungsansatz schenken?
Jetzt ist mir noch eine Frage eingefallen. Was ist wenn die Portnummer schon von einem anderem unabhängigen Programm belegt ist? Dann startet mein Programm nicht mehr, oder? Wie kann ich das verhindern?
Ja, super, es geht!
Aber ich verstehe noch nicht so genau was da passiert. könntest su mir das bitte erklären
Jetzt muss ich es nur noch schaffen in dem Hauptprogramm eine Funktion aufzurufen. Könntest du mir dabei bitte auch einen Lösungsansatz schenken?
Jetzt ist mir noch eine Frage eingefallen. Was ist wenn die Portnummer schon von einem anderem unabhängigen Programm belegt ist? Dann startet mein Programm nicht mehr, oder? Wie kann ich das verhindern?
Gruß, Harry
Hi. In einer Funktion sind alle Variablen lokal, d.h. du kannst von außen nicht auf HOST oder PORT in DoConnect zugreifen. Sie existieren also nur während des Funktionsaufrufes und werden danach vom Python Garbage Collector wieder gelöscht (es existiert kein Verweis mehr auf sie, also werden sie nicht mehr gebraucht). Wenn nun aber s gelöscht wird, wird der Socket gleich wieder geschlossen. Das soll verhindert werden. Also hab ich eine Liste außerhalb der Funktion definiert, in die s dann eingetragen wird. So existiert der Socket zwar nicht mehr als s, aber als Teil der Liste _sock und wird nicht gelöscht. Es ist egal, ob du eine Liste oder etwas anderes nimmst, nur bei einer Liste brauch ich kein global einzusetzen, damit ich auch aus der Funktion heraus schreibend zugreifen kann.
Dazu ist es unter anderem ganz nützlich, dass du den Socket noch weiter speicherst. So kannst du Daten darüber empfangen. Hier mal ein längeres Codebeispiel, was dein Modul schon mal in die Richtung ausbaut:HarryH hat geschrieben:Jetzt muss ich es nur noch schaffen in dem Hauptprogramm eine Funktion aufzurufen. Könntest du mir dabei bitte auch einen Lösungsansatz schenken?
Code: Alles auswählen
# -*- coding: UTF-8 -*-
import socket
import sys
import threading
_sock=[None]
HOST = 'localhost'
PORT = 65007
class Miniserver(threading.Thread):
def __init__(self,sock):
threading.Thread.__init__(self)
self.s=sock
def run(self):
while 1: # Empfange Anfragen vom 2. Programm
conn, addr = self.s.accept()
print 'Connected by', addr
while 1:
data = conn.recv(1024)
if not data: break
conn.close()
Funktion(data)
def Funktion(text):
print "Habe Nachricht empfangen: %s"%text
def DoConnect():
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
_sock[0]=s
serv=Miniserver(s)
serv.start()
print "Server gestartet"
except: #Hauptprogramm existiert, verbinde mit Programm
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.send('Hello, world')
s.close()
print "Funktion gestartet, beende mich..."
if __name__=="__main__":
DoConnect()
Danke! Funktioniert schon recht gut.
Nur habe ich nun das Problem, das mein Programm nicht beendet werden kann, da er bei 'self.s.accept()' wartet. Also auch wenn ich in meinem Hauptprogramm sys.exit() aufrufe läuft es weiter.
Was hat das schon wieder zu bedeuten?
Nur habe ich nun das Problem, das mein Programm nicht beendet werden kann, da er bei 'self.s.accept()' wartet. Also auch wenn ich in meinem Hauptprogramm sys.exit() aufrufe läuft es weiter.
Was hat das schon wieder zu bedeuten?
Gruß, Harry
Hi. Das bedeutet, dass der Thread in einer Endlosschleife steckt und beendet werden muss. Ich würde das ganz einfach so lösen, dass sich das Hauptprogramm mit sich selbst verbindet und dem Thread einen speziell definierten String schickt, auf den er sich dann beendet. Versuch (ungetestet):
Das self.quit in der Abfrage hat den Zweck, dass der Thread nicht von außen beendet werden kann. So musst du es im Hauptprogramm vor der Verbindung setzen und das kann nur das Hauptprogramm, nicht aber ein anders Pythonscript, was ja auch "zu Ende" an den Socket schicken könnte...
Code: Alles auswählen
class Miniserver(threading.Thread):
def __init__(self,sock):
threading.Thread.__init__(self)
self.s=sock
def run(self):
while 1: # Empfange Anfragen vom 2. Programm
conn, addr = self.s.accept()
print 'Connected by', addr
while 1:
data = conn.recv(1024)
if not data: break
conn.close()
if data == "zu Ende" and self.quit:
break
Funktion(data)
Hi. Das ist kein Problem, das wird er. Ein Thread ist ja ein Leichtgewichtprozess, der als unterprozess läuft. Damit ist er zwar zeitlich unabhängig von der Ausführung des Hauptprogrammes, aber trotzdem abhängig. Wenn der Prozess beendet wird, sollte auch der Thread beendet werden. Bestimmt ist es auch möglich, ihn explizit vom Hauptprogramm aus zu beenden, aber ich hab mich da noch weiter mit beschäftigt. Vielleicht weiß jemand anderes, wie das geht...
Hallo,
Das Modul läuft nun schon ziemlich gut!
Hier der Code:
Durch die Parameter 'funktion' und 'parameter' in 'DoConnect' kann man eine Funktion übergeben, welche nach doppeltem Aufruf des Programms gestartet werden soll.
Bei Beendigung des Programms, genügt es 'DoConnect' ohne Paramter aufzurufen. Dadurch wird "END" an den Miniserver übertragen und der Thread beendet.
Wer hat noch eine Idee zur Optimierung?
Was ist wenn die Portnummer schon von einem anderen unabhängigen Programm belegt ist? Dann startet mein Programm nicht mehr, oder? Wie kann ich das verhindern?
Das Modul läuft nun schon ziemlich gut!
Hier der Code:
Code: Alles auswählen
# -*- coding: iso-8859-1 -*-
import socket
import sys
import threading
#Socketspeicher
_sock=[None]
#Verbinden
def DoConnect(text="END", funktion=None, parameter=None):
HOST = "localhost"
PORT = 65012
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
_sock[0] = s
serv = Miniserver(s, funktion, parameter)
serv.start()
print "Server gestartet"
except:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.send(text)
s.close()
return "CLOSE"
#Server
class Miniserver(threading.Thread):
def __init__(self, sock, funktion, parameter):
threading.Thread.__init__(self)
self.s = sock
self.funktion = funktion
self.parameter = parameter
def run(self):
while 1:
conn, addr = self.s.accept()
data = conn.recv(1024)
conn.close()
if data == "END":
print "Server beendet"
break
print "Server hat folgendes Signal erhalten: %s"%data
if self.funktion:
self.funktion(self.parameter)
print "Übergebene Funktion wurde gestartet"
if __name__=="__main__":
DoConnect()
Bei Beendigung des Programms, genügt es 'DoConnect' ohne Paramter aufzurufen. Dadurch wird "END" an den Miniserver übertragen und der Thread beendet.
Wer hat noch eine Idee zur Optimierung?
Was ist wenn die Portnummer schon von einem anderen unabhängigen Programm belegt ist? Dann startet mein Programm nicht mehr, oder? Wie kann ich das verhindern?
Gruß, Harry
Hallo,
Habe nun auch den Rest hinbekommen. Dieses Modul kann nun auch für mehrere Programme verwendet werden. Jedes dieser Programme erhält dann eine eigene noch nicht existierende Hostnummer.
Mit der an die Funtion 'DoConnect' zu übergebenden Variable 'progname' wird der Name des Programms übergeben. Für jeden neuen Namen wird dann eine neue Host-Nummer vergeben.
Mit der Funktion 'DoDisconnect' wird dann das Socket für das jeweilige Programm entfernt.
Der Bereich der zu vergebenden Hostnummern kann nartürlich vergrößert oder verkleinert werden.
Habe nun auch den Rest hinbekommen. Dieses Modul kann nun auch für mehrere Programme verwendet werden. Jedes dieser Programme erhält dann eine eigene noch nicht existierende Hostnummer.
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):
if not progName or type(progName) != str:
raise ValueError, 'Value must be a string and may be not empty'
HOST = socket.getfqdn()
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
serv = Miniserver(s, progName, port, funktion, parameter)
serv.start()
print "Port %s gestartet"% port
break
except:
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"
#Verbindung trennen
def DoDisconnect():
DoConnect("!%END%!")
#Server
class Miniserver(threading.Thread):
def __init__(self, sock, progName, port, funktion, parameter):
threading.Thread.__init__(self)
self.s = sock
self.progName= progName
self.port= port
self.funktion = funktion
self.parameter = parameter
def run(self):
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
Mit der Funktion 'DoDisconnect' wird dann das Socket für das jeweilige Programm entfernt.
Der Bereich der zu vergebenden Hostnummern kann nartürlich vergrößert oder verkleinert werden.
Gruß, Harry