Plötzlich läuft mein Script nicht mehr. Venv-Umgebeung

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.
kiaralle
User
Beiträge: 132
Registriert: Donnerstag 19. August 2021, 19:11

Hallo,

ich greife mit pymodbus auf meine Wechselrichter zu.
Seit der Umstellung auf venv-Umgebung funktionieren nicht einmal die kleinsten Scripte

Code: Alles auswählen

parser = argparse.ArgumentParser()
parser.add_argument("adresse", type=int, help="Inverter Adresse")
parser.add_argument("register", type=int, help="Input-Register")
args = parser.parse_args()

inverter_adresse = args.adresse
modbus_register = args.register


client = ModbusSerialClient(
    port="/dev/ttyUSB0",
    startbit = 1,
    databits=8,
    parity="N",
    stopbits=2,
    errorcheck="crc",
    baudrate=9600,
    method="RTU",
    timeout=1
)

client.connect()

result = client.read_input_registers(modbus_register, 1, inverter_adresse)
print(result.registers)

client.close()

Fehlermeldung:
Traceback (most recent call last):
File "/var/www/html/solarsteuerung-3phasig/Tool/readinputregister.py", line 21, in <module>
client = ModbusSerialClient(
^^^^^^^^^^^^^^^^^^^
TypeError: ModbusSerialClient.__init__() got an unexpected keyword argument 'startbit'
Jetzt hänge ich etwas in den Seilen.

Ich rufe über venv auf:
/home/pi/solar/bin/python3 /var/www/html/solarsteuerung-3phasig/Tool/readinputregister.py 1 18
Ohne venv (älteres Rasperry-Pi-OS) funktioniert das.
Das neuere Betriebssystem verlangt venv, was ja auch besser und sicherer ist.

Gruß Ralf
Sirius3
User
Beiträge: 18250
Registriert: Sonntag 21. Oktober 2012, 17:20

Du hast wahrscheinlich das falsche Paket für ModbusSerialClient installiert. pymodbus kennt und kannte noch nie ein startbit-Argument.
kiaralle
User
Beiträge: 132
Registriert: Donnerstag 19. August 2021, 19:11

Jetzt mach mich nicht fertig, Echt?

Im Code steht

Code: Alles auswählen

from pymodbus.client import ModbusSerialClient
also machte ich >>>> pip3 install pymodbus

Code: Alles auswählen

docutils   0.21.2  /home/pi/solar/lib/python3.11/site-packages pip
pip        24.2    /home/pi/solar/lib/python3.11/site-packages pip
pymodbus   3.7.2   /home/pi/solar/lib/python3.11/site-packages pip
pyserial   3.5     /home/pi/solar/lib/python3.11/site-packages pip
RPi.GPIO   0.7.1   /home/pi/solar/lib/python3.11/site-packages pip
setuptools 66.1.1  /home/pi/solar/lib/python3.11/site-packages pip
statistics 1.0.3.5 /home/pi/solar/lib/python3.11/site-packages pip
https://pymodbus.readthedocs.io/en/latest/index.html sollte doch mein Ziel sein.
Sirius3
User
Beiträge: 18250
Registriert: Sonntag 21. Oktober 2012, 17:20

Aber was hattest Du auf Deinem alten System, wo es noch funktioniert hatte, installiert?
kiaralle
User
Beiträge: 132
Registriert: Donnerstag 19. August 2021, 19:11

Hab das alte System noch mal gestartet.
pymodbus 3.5.0 /home/pi/.local/lib/python3.9/site-packages pip
Die Version ist älter. Aber sonnst?

Ich habe gerade in /home/pi/.local/lib/python3.9/site-packages/pymodbus/serial.py angeschaut.
startbit gab und gibt es nicht.
Warum funktioniert es dann hier?

Gruß Ralf

Edit: das löschen vom startbit=1 im Code bringt hier keine Fehler. Hmm
Benutzeravatar
__blackjack__
User
Beiträge: 13999
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@kiaralle: Wenn ich mal raten müsste heisst das Argument `startbits` und nicht `startbit`, denn es heisst ja auch `stopbits` und nicht `stopbit`.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
Benutzeravatar
pillmuncher
User
Beiträge: 1529
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@kiaralle:

Seit dem Commit f0d6842 funktioniert startbit nicht mehr, weil das davor von **kwargs aufgefangen wurde, das mit dem genannten Commit entfernt wurde. Du hättest vorher auch foobar oder Schornsteinfeger schreiben können, ohne dass es einen Fehler gegeben hätte.

Hier der Code der __init__() Methode:

Code: Alles auswählen

def __init__(
        self,
        port: str,
        framer: FramerType = FramerType.RTU,
        baudrate: int = 19200,
        bytesize: int = 8,
        parity: str = "N",
        stopbits: int = 1,
        **kwargs: Any,
    ) -> None:
Beachte den letzten Parameter.
In specifications, Murphy's Law supersedes Ohm's.
kiaralle
User
Beiträge: 132
Registriert: Donnerstag 19. August 2021, 19:11

Danke für eure Tipps. Fehler habe ich Korrigiert.

Jetzt muss ich noch finden was ich noch nicht installiert haben könnte.
Mein Script mag nicht auf den USB-RS485 zugreifen.
kiaralle
User
Beiträge: 132
Registriert: Donnerstag 19. August 2021, 19:11

Frage in die Runde,

könnte es sein, das venv eventuell rechte nicht erteilt werden?

Im alten System, läuft die Software ja mit dem System-Pyton und dessen Module.
Benutzeravatar
noisefloor
User
Beiträge: 4172
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

nein. Dein Python Skript läuft mit den Rechen, mit denen du es startest. Ob die Module systemweit oder lokal oder im venv installiert sind spielt keine Rolle. Eine Datei hat ja per se auch keine Systemrechte, im Sinne von, dass sie etwas darf.

Du müsstest mal die Rechte des Benutzers prüfen, unter dem das Skript läuft. Unter Linux muss man AFAIK Mitglied der Gruppe "dialout" sein, um aus die seriellen Schnittstellen zugreifen zu können.

Gruß, noisefloor
kiaralle
User
Beiträge: 132
Registriert: Donnerstag 19. August 2021, 19:11

Gruppe "dialout" ... ist der user pi drinnen.
Prüfe ich aber nocheinmal.

Bin mal etwas Frech aus venv raus und habe mit dem Befehl

pip3 install --break-system-packages ....

Pakete installiert.
Kein Zugriff auf USB.

Ich checke die Gruppe noch mal. Kann ja nicht sein. :(

Passt:

id pi
uid=1000(pi) gid=1000(pi) groups=1000(pi),4(adm),20(dialout),24(cdrom),27(sudo),29(audio),44(video),46(plugdev),60(games),100(users),102(input),105(render),106(netdev),995(spi),994(i2c),993(gpio),115(lpadmin)
Benutzeravatar
noisefloor
User
Beiträge: 4172
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

passt mal bitte die _komplette_ Fehlermeldung = den Stack Trace, den du bekommst.

Gruß, noisefloor
kiaralle
User
Beiträge: 132
Registriert: Donnerstag 19. August 2021, 19:11

Code: Alles auswählen

try:
    client = ModbusSerialClient(
        port="/dev/ttyUSB0",
        databits=8,
        parity="N",
        stopbits=2,
        baudrate=9600,
        method="RTU"
        )
except:
    print("Keine Verbindung zum USB-RS485-Umsetzer")
    sys.exit(1)
Ich bekomme ja keinen, da ja meine Exception mangelhaft ist und ich nicht weiß wie ich dies lösen könnte.
kiaralle
User
Beiträge: 132
Registriert: Donnerstag 19. August 2021, 19:11

Hab am Script geschraubt.

wenn ich

Code: Alles auswählen

client = ModbusSerialClient(
        port="/dev/ttyUSB0",
        databits=8,
        parity="N",
        stopbits=2,
        baudrate=9600,
        method="RTU"
        )
frei in den Code stelle, bekomme ich
Traceback (most recent call last):
File "/home/pi/./steuerung.py", line 51, in <module>
client = ModbusSerialClient(
^^^^^^^^^^^^^^^^^^^
TypeError: ModbusSerialClient.__init__() got an unexpected keyword argument 'databits'
Ich denke da stimmt einiges nicht, nicht mehr zur letzten Version von pymodbus
Benutzeravatar
noisefloor
User
Beiträge: 4172
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
Ich bekomme ja keinen, da ja meine Exception mangelhaft ist
Schönes Beispiel, warum nackte try..except keine gute Idee sind - weil eben alle Fehler inkl. Programmierfehlern einfach weggebügelt werden. Im gegebenen Fall weißt du also gar nicht, ob du keine Verbindung bekommst, weil das Programm vorher schon abbricht.

Da musst du halt mal die Doku von pymodbus lesen und deinen Code auf den Stand der Dinge anpassen.

Gruß, noisefloor
kiaralle
User
Beiträge: 132
Registriert: Donnerstag 19. August 2021, 19:11

Ich bin gerade dabei.
Da wird wieder Arbeit :D
kiaralle
User
Beiträge: 132
Registriert: Donnerstag 19. August 2021, 19:11

So, mal ganz anderen Weg.

Neues Skript und baugleichen USB-to-RS458 von Wireshark am Laptop, Linux Mint.

Code: Alles auswählen

from pymodbus.client import ModbusSerialClient

client = ModbusSerialClient(port="/dev/ttyUSB0", baudrate=9600, stopbits=2, bytesize=8, timeout=1, parity="N")

if client.connect():
    print("Verbindung ok")
else:
    print("keine Verbindung")

abfrage_wr1 = client.read_input_registers(0, 1, 1)
if not abfrage_wr1.isError():
    print("Gerät erreichbar")
else:

    print("Gerät nicht erreichbar")


Am Laptop alles ok.

Am Raspberry bekomme ich eine Fehlermeldung
pi@steuerung:~ $ python3 ./verbindung.py
module 'serial' has no attribute 'serial_for_url'
keine Verbindung
module 'serial' has no attribute 'serial_for_url'
Traceback (most recent call last):
File "/home/pi/./verbindung.py", line 17, in <module>
abfrage_wr1 = client.read_input_registers(0, 1, 1)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/pymodbus/client/mixin.py", line 102, in read_input_registers
return self.execute(pdu_reg_read.ReadInputRegistersRequest(address, count, slave=slave))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/pymodbus/client/base.py", line 236, in execute
raise ConnectionException(f"Failed to connect[{self!s}]")
pymodbus.exceptions.ConnectionException: Modbus Error: [Connection] Failed to connect[ModbusSerialClient /dev/ttyUSB0:0]

Benutzeravatar
grubenfox
User
Beiträge: 601
Registriert: Freitag 2. Dezember 2022, 15:49

Naja, wenn `client.connect()` kein `True` zurückliefert, dann macht es auch keinen Sinn aus dem toten `client` noch irgendwelche Input-register lesen zu wollen.
Also den unteren Teil vom Codel am besten unter das "Verbindung OK"... Dann entfallen wenigsten die überflüssigen Folgefehler falls `client.connect()` nur ein False liefert.

Code: Alles auswählen

from pymodbus.client import ModbusSerialClient

client = ModbusSerialClient(port="/dev/ttyUSB0", baudrate=9600, stopbits=2, bytesize=8, timeout=1, parity="N")

if client.connect():
    print("Verbindung ok")
    abfrage_wr1 = client.read_input_registers(0, 1, 1)
    if not abfrage_wr1.isError():
        print("Gerät erreichbar")
    else:
        print("Gerät nicht erreichbar")
else:
    print("keine Verbindung")
Kann man dem client-Objekt im Fehlerfall noch irgendwelche hilfreichen Informationen entlocken? Einfach nur ein "keine Verbindung" ist ja etwas sehr mager an Information...
Ansonsten noch eine Frage: ist das groß geschriebene "USB0" beim Port korrekt? Ich habe hier unter "/dev/*" nur alle möglichen Kleinbuchstaben usw.. kein Device mit Großbuchstaben im Namen. Aber es mangelt hier auch am USB-RS485-Konverter. Kann ich also nichts testen...
kiaralle
User
Beiträge: 132
Registriert: Donnerstag 19. August 2021, 19:11

Naja, wenn `client.connect()` kein `True` zurückliefert,
Das ist schon klar. Ich wollte nur wissen wo der Fehler aufläuft. Ist nur ein Testscript.
Und wenn "Gerät erreichbar" kommt, sollte auch der Modbus kommen.
Das tut er im Fehlerfall "Gerät nicht erreichbar" auf dem Raspberry auch nicht.
Soweit passt das ja zum testen.

Ich erstelle jetzt zum testen eine venv mit all den Modulen welche ich im alten, laufenden System habe.
Gleichzeitig schau ich mal ob ich 32 oder 64 bit auf beiden gleich installiert habe. Also das Raspberry OS
Aber es macht wenig Sinn mit alten Modulen zu arbeiten. Das holt einen immer wieder ein.
Besser Fehler suchen.
Antworten