Python objektum és globális változó

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

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!']

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)

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

http://www.redphoto.hu

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))

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!

http://www.redphoto.hu

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

http://www.redphoto.hu