Sziasztok,
GPS trackereket szeretnék saját szerveren kezelni. A traccar javas cucc sajnos eléggé ágyuval verébre, meg szeretnék tanulni is.
Szóval találtam egy Python kódot ami kezeli az egyik eszközömet: https://github.com/durian/tk102-server
Egy másik eszközhöz is szeretném használni (más adatformátum), ezért nekiálltam átalakítani.
Az eredeti program, könyvtárak és fájlok létrehozásával oldotta meg az adatok tárolását, de mivel nekem MQTT üzenet kell csak az aktuálisan küldött üzenetről ezért elég lenne mindent a memóriában kezelni.
Tehát elkezdem átírni és amikor a memóriában tárolásra jutott a sor elakadtam.
Itt van a lényeg a kódból
https://pastebin.com/i7GGH5KP
A kérdésem: hogyan lehet egy "globális" változót készíteni amit az objektum és a main program is elér? ###-ek között van a leírás, hogy hol módosítanám és hol kéne kiolvasnom a tárolt tömböt. (a kívül lértehozott változó és a global kulcsszó az objektumban nem működik.)
A RequestHandler-nek kéne valahogy egy plusz paramétert adni a tömbbel. Csak amint ezt teszem az argumentumok száma nem egyezik meg és elszáll a program (teljesen jogosan).
Ezt lehet valahogy máshogyan megadni?
server = Server(address, RequestHandler)
Üdv: redman
- 916 megtekintés
Hozzászólások
Amit a root namespace-ben definiálsz (class -on kívül bárhol) az global lesz és elérhető és módosítható. Arra ügyelj, hogy újra definiáláskor egy másik változó jön létre és az nem fog látszani a function-ön kívül, ha ilyet akarsz, akkor a functon elején global -ban kell megadni a változót pl.:
def change():
trackers.append("from function")
trackers = ["hello"]
change()
print("After change", trackers)
def redefine():
trackers = ["not hello!"]
redefine()
print("After redefine", trackers)
def redefine_with_global():
global trackers
trackers = ["not hello!"]
redefine_with_global()
print("After redefine_with_global", trackers)
Output:
'After change', ['hello', 'from function']
'After redefine', ['hello', 'from function']
'After redefine_with_global', ['not hello!']
- A hozzászóláshoz be kell jelentkezni
Ha nem akarsz global változókat (általában érdemes elkerülni), akkor én a server objektumba definiálnék egy változót:
import SocketServer, threading, time
class RequestHandler(SocketServer.BaseRequestHandler):
def __init__(self, request, client_address, server):
SocketServer.BaseRequestHandler.__init__(self, request, client_address, server)
def handle(self):
data = self.request.recv(1024)
print("Got data", data)
self.server.recv.append(data)
server = SocketServer.TCPServer(('', 1235), RequestHandler)
server.recv = []
t = threading.Thread(target=server.serve_forever)
t.setDaemon(True) # don't hang on exit
t.start()
while 1:
time.sleep(1)
print("All recv", server.recv)
- A hozzászóláshoz be kell jelentkezni
Valamiért egyik sem működik. (Köszönöm a segítéget)
Nem lehet, hogy az egy másik Thread és azok nem látják egymást?
Kiíratom a tömb méretét amikor hozzáadom az 1 lesz, a main-ben viszont továbbra is 0
- A hozzászóláshoz be kell jelentkezni
A thread nem probléma (lásd második példát), de ha multi-process a server akkor igen. (és úgy tűnik, hogy az)
Innen https://github.com/durian/tk102-server/blob/master/tk102-server.py#L325
próbáld a SocketServer.ForkingMixIn -t SocketServer.ThreadingMixIn -el helyettesíteni, vagy itt egy példa a processek közti változómegosztásra (ez is viszonylag egyszerű):
import SocketServer, threading, time, multiprocessing
class RequestHandler(SocketServer.BaseRequestHandler):
def __init__(self, request, client_address, server):
SocketServer.BaseRequestHandler.__init__(self, request, client_address, server)
def handle(self):
data = self.request.recv(1024)
print("Got data", data)
self.server.recv.append(data)
shared = multiprocessing.Manager()
server = SocketServer.ForkingTCPServer(('', 1235), RequestHandler)
server.recv = shared.list()
t = threading.Thread(target=server.serve_forever)
t.setDaemon(True) # don't hang on exit
t.start()
while 1:
time.sleep(1)
print("All recv", list(server.recv))
- A hozzászóláshoz be kell jelentkezni
Nagyon köszönöm, ez volt a megoldás.
Innen már tovább tudtam menni és dictionary-t használni, így nem kell a tömbből keresgetnem a trackert, hanem az imei számával egyedivé tudom tenni az asszociatív tömbben.
Ekkor viszont a te példádhoz képest ennyit kell módisítani
server.recv = shared.list() -> server.recv = shared.dict()
Egy virtuális sört küldök neked. Ha esetleg találkoznánk valamikor akkor pedig egy igazira is a vendégem vagy. :)
Köszönöm!
- A hozzászóláshoz be kell jelentkezni
[Feliratkozás]
- A hozzászóláshoz be kell jelentkezni
Még egy kapcsolódó kérdés:
Mellékhatásként megjelenik az a probléma, hogy a létrehozott, de "nem működő" processek nem halnak el.
Ha pl valaki beküld a programnak egy üres stringet, azt a program kivédi, mert nem dolgozza fel, de a process ugyanúgy létrejön.
os.kill(pid,signal.SIGTERM)
#vagy
os.kill(pid,signal.SIGKILL)
nem tudja megölni.
Ha lefuttatok egy linux parancsot: kill -9 pid
Akkor a process meghal, de defunct lesz a process listában.
Ezen hogy lehet segíteni?
Ez gondolom azért eszi az erőforrásokat (ha nem is sokat), meg hát a tudat... :)
Üdv: redman
- A hozzászóláshoz be kell jelentkezni
Nem világos, hogy fent pontosan mit is csináltál végül, de ilyen akkor van, amikor a vezérlő processed nem waitel a forkolt gyermekeire. Zombinak hívják őket, a daemonod megálláskor az init ki fogja takarítani, de jobb lenne, ha a kód proper módon figyelne erre.
- A hozzászóláshoz be kell jelentkezni
self.request.settimeout(3) a handle rész elejére megoldja a problémát
- A hozzászóláshoz be kell jelentkezni
Köszönöm, este megnézem.
- A hozzászóláshoz be kell jelentkezni