Zugriff auf Modul welches bereits aktiv ist

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.
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

Guten Abend,

ich habe für Kodi ein BMW IBus Addon erstellt, was als Service läuft.
Nun möchte ich aber mit nen zweiten script auf diverse variablen zugreifen.
Nach durchforsten des Netztes lässt sich das mit import nicht lösen.

Ein Workaround wäre, wenn ich variablen in Kodi als Property ablege. Aber meiner Ansicht keine sinnvolle Lösung.
Gibt es denn eine Möglichkeit an bereits aktive module ran zu kommen?

viele Grüße
empty Sig
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Nein.

Das nennt sich üblicherweise Interprocess-Communication, je nach Framework (BMW IBus?) gibt es Funktionen die du dafür benutzen kannst.
the more they change the more they stay the same
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

ist pickle vielleicht die lösung?

http://stackoverflow.com/questions/3066 ... her-script

http://docs.python.org/library/pickle.html

so wie ich das lese, lassen sich auch object-instancen austauschen. richtig
empty Sig
BlackJack

@harryberlin: Das kann Teil einer Lösung sein aber das löst ja nicht das Problem wie die Daten von einem zum anderen Prozess kommen.
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

@Dav1d:
Hab OSMC aufn Rasp laufen und im Auto(BMW) an der Datenleitung(IBus) ein IBusInterface (Serialport), damit ich mit dem Bordmonitor Kodi steuern kann.
https://www.youtube.com/watch?v=dRfnGiZ3O88

Meinst du mit Nein, da gibt es grundsätzlich keine Lösung, oder was meinst du mit frameworks?

@BlackJack
Kannst du mir ein Tipp geben wonach ich suchen soll?
empty Sig
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

harryberlin hat geschrieben:@Dav1d:
Hab OSMC aufn Rasp laufen und im Auto(BMW) an der Datenleitung(IBus) ein IBusInterface (Serialport), damit ich mit dem Bordmonitor Kodi steuern kann.
https://www.youtube.com/watch?v=dRfnGiZ3O88
Generell nicht möglich so wie du dir das vorstellst, an sich ist es durchaus möglich. Dein 'erstes' Skript muss ein Interface bereitstellen damit dein 'zweites' Skript Daten lesen kann.

Warum kommt dir das Ablegen der Properties im Kodi nicht sinnvoll vor? Wenn kodi (das was ich mit Framework meinte) bereits einen Weg bietet Daten zwischen Prozessen zu sharen ist das doch super.

PS: Code als .pyo zu verteilen bringt nicht viel (sehe ich auch als schlechten Stil an und es kann dir passieren, dass der Code nur auf einer Python-Version läuft).
PS2: An dem Code kann man einiges verbessern.
the more they change the more they stay the same
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

Hab hier gerade noch was gefunden. http://stackoverflow.com/questions/6920 ... -in-python
Wenn ich das richtig verstehe, dann müsste ich mir in jedes script einen sender/empfänger bauen.
Und dann hin und her schicken was ich will, mit entsprechender auswerte logic.
Warum kommt dir das Ablegen der Properties im Kodi nicht sinnvoll vor? Wenn kodi (das was ich mit Framework meinte) bereits einen Weg bietet Daten zwischen Prozessen zu sharen ist das doch super.
Weil ich mir vorgestellt hatte direkt eine funktion aus nen script anzusteuern. z.B. vom obc.py die get funktionen.
oder direkt IBUS zu nutzen.

PS. Ja mir ist bewusst, dass man es decompilen kann. Selbst schon gemacht. ;)
Aber zumindest hast schon mal die source gefunden.
PSS. Ja mir wurde schon mehrfach geraten/gemahnt vom global weg zu kommen.
und ja ich weiß auch, dass mein code viel trash ist. :(
Nur derzeit bin ich einfach froh, dass der code läuft. bin leider auch nicht irgend ein it student der versucht hier seine hausaufgaben leicht zu lösen.
Einen wirklich python profi kenne ich auch nicht.
wenn du mich unterstützden möchtest, dann nehme ich deine hilfe gerne an.

komisch dass hier die e-mailben. nicht geht.....
empty Sig
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

harryberlin hat geschrieben:Hab hier gerade noch was gefunden. http://stackoverflow.com/questions/6920 ... -in-python
Wenn ich das richtig verstehe, dann müsste ich mir in jedes script einen sender/empfänger bauen.
Und dann hin und her schicken was ich will, mit entsprechender auswerte logic.
Im Grunde ja. Aber es kann durchaus sein, dass es um einiges leichter geht in deiner Umgebung. So wie ich das sehe hast du ein Kodi-Plugin (IBusConnector), dieses Plugin hat ein paar Variablen welche du gerne an ein anderes Skript weitergeben möchtest. Läuft das 2. Skript auch als Kodi Plugin? Wenn *ja* sind die Chancen hoch, dass es recht einfach geht (Kodi hat sicher i-was das das möglich macht).
harryberlin hat geschrieben:PS. Ja mir ist bewusst, dass man es decompilen kann.
PSS. Ja mir wurde schon mehrfach geraten/gemahnt vom global weg zu kommen.
und ja ich weiß auch, dass mein code viel trash ist. :(
Warum dann überhaupt 'kompeliert' ausliefern? Ich denke so gut wie jeder der Regulären hier würde dir dabei helfen (solange du lernen willst), aber dazu musst du Code zeigen oder Fragen stellen.
harryberlin hat geschrieben:Nur derzeit bin ich einfach froh, dass der code läuft. bin leider auch nicht irgend ein it student der versucht hier seine hausaufgaben leicht zu lösen.
Einen wirklich python profi kenne ich auch nicht.
wenn du mich unterstützden möchtest, dann nehme ich deine hilfe gerne an.
Wie gesagt denke jeder hier würde das machen, ansonsten kannst du mir gerne Fragen im IRC stellen (auch anderen) bzw. deinen Code durchgehen -> chat.freenode.net/#python.de
the more they change the more they stay the same
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

compiliert weil, doch ne recht menge know how und verbrachte zeit vom handling der nachrichten drin steckt, was sicher einige interessiert, die geld damit machen wollen.
hab natürlich bereits gelesen, dass es gar nicht gern gesehen wird, wenn es "compiliert" ist.

das andere script ist ebenfalls im addon drin, aber wird eben erst bei bedarf aufgerufen.
ich bin halt auch eher ein fan von direktem austuasch, statt über zig schnittstellen.

die lösung aus dem link kann ich wohl erst am we mal versuchen umzusetzen.
empty Sig
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

harryberlin hat geschrieben:compiliert weil, doch ne recht menge know how und verbrachte zeit vom handling der nachrichten drin steckt, was sicher einige interessiert, die geld damit machen wollen.
hab natürlich bereits gelesen, dass es gar nicht gern gesehen wird, wenn es "compiliert" ist.
Üblicherweise löst man das mit Lizenzen.
harryberlin hat geschrieben: das andere script ist ebenfalls im addon drin, aber wird eben erst bei bedarf aufgerufen.
ich bin halt auch eher ein fan von direktem austuasch, statt über zig schnittstellen.
Wie und von was wird es aufgerufen?
the more they change the more they stay the same
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

naja, mal ehrlich, wie will man sowas nachweisen, wenn nicht gerade der ganze code kopiert ist.

das andere skript wird von kodi aus aufgerufen, per runscript. die default.py
möchte damit z.b. ein window öffnen.
bzw. wollte damit die funktion in obc.py aufrufen. sowas müsste ich jetzt über die schnittstelle anstoßen.
d.h. ich sollte so wenig wie möglich ins default script coden.
das wäre ja ein gangbarer weg. dann kann ich evtl. auf bidirektionale kommunikation verzichten.
empty Sig
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Laut Dokumentation kannst du dem Skript Argumente mit geben, wenn es dir reicht, dass das Skript einmal die Variablen erhält, dann reicht das ja.
the more they change the more they stay the same
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

ich glaub das hast du falsch verstanden, oder überlesen.
ich würde schon gern werte austauschen und functionen auslösen. wenn ich es jedoch sinnvoll löse, dann reicht es mir, wenn ich nur functionen auslöse. wie z.B. nicht die obc(OnBordComputer) werte holen, sondern das ganze obc zeugs in dem script handle, was eh aktive ist.
also entweder in events oder core solch einen "Empfänger"
empty Sig
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

Ich habe jetzt mal versucht ne klasse aus dem bereits verlinkten zu schustern.
Würde das mit dem import so funktionieren, oder macht man das besser on top?
Und überhaupt, was sagt ihr dazu?

Code: Alles auswählen

class CmdReceiver:
    def __init__(self):
        from multiprocessing.connection import Listener

        address = ('localhost', 6000)  # family is deduced to be 'AF_INET'
        self.listener = Listener(address, authkey='secret password')
        self.conn = self.listener.accept()
        self.run = True
        print 'connection accepted from', self.listener.last_accepted

    def start(self):
        while self.run:
            msg = self.conn.recv()
            # do something with msg
            if msg == 'close':
                self.conn.close()
                break
        self.listener.close()

    def stop(self):
        self.run = False
        
MyReceiver = CmdReceiver()
MyReceiver.start()
empty Sig
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

hab nun mal einiges ausprobiert, aber das script kommt immer nur bis zum start.
irgendwie connected wohl nix.
und der port wird dann auch nicht mehr frei, wenn ich abbreche.

habt ihr nen rat für mich?

Code: Alles auswählen

class CmdReceiver():
    def __init__(self):
        print 'server init'
        self.address = ('localhost', 6000)  # family is deduced to be 'AF_INET'
        self.run = True

    def start(self):
        Thread(target=self.start_thread).start()

    def start_thread(self):
        print 'server start'
        self.listener = Listener(self.address, authkey='bmwibus')
        self.conn = self.listener.accept()
        print 'server connection accepted from', self.listener.last_accepted
        while self.run:
            msg = self.conn.recv()
            # do something with msg
            print msg
            if msg == 'close':
                self.conn.close()
                break
        self.listener.close()

    def stop(self):
        print 'server stop'
        self.run = False
        self.listener.close()

    def __del__(self):
        print 'server del'
        self.run = False
        self.listener.close()



class CmdSender:
    def __init__(self):
        print 'client init'
        address = ('localhost', 6000)
        self.conn = Client(address, authkey='bmwibus')

    def send(self, msg):
        print 'client send %s' % msg
        self.conn.send_bytes(msg)
        # can also send arbitrary objects:
        # conn.send(['a', 2.5, None, int, sum])

    def stop(self):
        print 'client stop'
        self.conn.close()

    def __del__(self):
        self.run = False
        self.conn.close()

MyReceiver = CmdReceiver()
MySender = CmdSender()

MyReceiver.start()
MySender.run
MySender.send('lalala')
time.sleep(5)
MySender.stop()
MyReceiver.stop()
empty Sig
BlackJack

@harryberlin: Ein ganz wichtiger Rat wäre: Lass die Finger von `__del__()`! Es ist nicht garantiert wann und ob die Methode aufgerufen wird und ihr Vorhandensein kann sogar begünstigen das sie nie aufgerufen wird. Die Methode sollte man nur implementieren wenn man genau weiss was die Speicherverwaltung von Python garantiert und was *nicht*, und dann auch nur wenn man externe Ressourcen verwalten muss, von denen Python nichts weiss. Das ist hier nicht der Fall soweit ich das sehe.

Wenn man `Thread` in einer Klasse verwendet um in einer `start()`-Methode eine andere Methode in dieser Klasse asynchron zu starten, wäre es einfacher diese andere Methode `run()` zu nennen und von `Thread` zu erben.

Der Receiver kann so wie er da steht soweit ich das sehe nur von einer Gegenstelle einmal eine Verbindung annehmen und bearbeiten.

Ist das überhaupt das was Du tatsächlich laufen lässt? Denn in Zeile 60 sollte es einen `AttributeError` geben weil `CmdSender` gar kein `run`-Attribut kennt.
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

ok, del fliegt raus.

run oder start, da war ich tatsächlich hin und her gerissen :D
das mit der thread vererbung versteh ich grad nicht.

und ja du hast recht, das wäre dann als nächstes meine frage gewesen.
wenn die verbindung unterbrochen wird, müsste man es wieder starten.
gibt es bessere lösungen?

das mit zmq und argparse hab ich auch versucht, aber es passiert genauso nix.
empty Sig
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

ich glaub ich habs :)

zwar noch nicht als klasse, aber ich sehe etwas.
und das müsste dann auch ohne verbindungsunterbrechung laufen.

Code: Alles auswählen

import zmq
from threading import Thread

def server_run():
    # server
    context = zmq.Context()
    socket = context.socket(zmq.REP)
    socket.bind('tcp://127.0.0.1:5555')
    while True:
        msg = socket.recv()
        if msg == 'zeromq':
            socket.send('ah ha!')
        else:
            socket.send('...nah')

def client_send(msg):
    # client
    context = zmq.Context()
    socket = context.socket(zmq.REQ)
    socket.connect('tcp://127.0.0.1:5555')
    socket.send(msg)
    msg = socket.recv()
    print msg

Thread(target=server_run).start()
client_send('zeromq')
edit:
hab über die Thread-Vererbung noch mal drüber nachgedacht, meinst du das so?
jetzt mal schnell hier runter geschrieben.
Bin mit classen nicht so bewandert.

Code: Alles auswählen

class CmdReceiver(Thread):
    def __ini__(self):
        self.target = run
        self.run = True

    def start(self):
        self.start()

    def run(self):
        while self.run:
            pass

    def stop(self):
        self.run = False
empty Sig
BlackJack

@harryberlin: Mit von `Thread` erben war gemeint von `Thread` zu erben (ungetestet):

Code: Alles auswählen

from __future__ import absolute_import, division, print_function
from contextlib import closing
from threading import Thread
# ...


class CmdReceiver(Thread):

    def __init__(self):
        print('server init')
        Thread.__init__(self)
        self.address = ('localhost', 6000)
        self.stop_requested = False
        self.listener = None
 
    def run(self):
        print('server start')
        with closing(
            Listener(self.address, authkey='bmwibus')
        ) as self.listener:
            with closing(self.listener.accept()) as connection:
                print(
                    'server connection accepted from',
                    self.listener.last_accepted
                )
                while not self.stop_requested:
                    message = connection.recv()
                    # 
                    # Do something with `message`.
                    # 
                    print(message)
                    if message == 'close':
                        break
 
    def stop(self):
        print('server stop')
        self.stop_requested = True
        self.listener.close()
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

ich glaub ich bleib bei zmq, weil "multiprocessing.connection" vermutlich auch nur eine verbindung zulässt.
zmq müsste ja auch mehrere clients zulassen.

zur klasse:
Ok bei Thread.__init__(self) komm ich noch mit, dass er sich sozusagen einrichtet.
Aber legt der dann gleich los und weiß auch was auszuführen ist?
Ich sehe nirgends ein target oder start()
empty Sig
Antworten