Seite 1 von 1

"Can only concatenate str (not "bytes") to str"

Verfasst: Dienstag 11. Oktober 2022, 16:10
von fcutim
Moin,

ich bin aktuell dabei, ein GSM Modul über Python anzusteuern. Nun aber bekomme ich eine Fehler beim ausführen des Programmes ausgespuckt. Das Programm soll an "COM7" den Befehl "AT" senden, und soll vorher noch ausgeben, ob der Port offen ist. Das Programm gibt noch an "COM7 ist offen", stürzt aber dann mit dem Fehler code "Can only concatenate str (not "bytes") to str" ab.

Hat jemand davon eine Ahnung wie ich das beheben kann?

Code:

Code: Alles auswählen


import serial, time

def serial_def():
    ser = serial.Serial()
    ser.port = "COM7"
    ser.baudrate = 9600
    ser.bytesize = serial.EIGHTBITS 
    ser.parity = serial.PARITY_NONE 
    ser.stopbits = serial.STOPBITS_ONE 
    ser.timeout = 2              
    ser.xonxoff = False     
    ser.rtscts = False     
    ser.dsrdtr = False       
    ser.writeTimeout = 2
    ser.open()

    if ser.isOpen():
         print(ser.name + ' is open...')

    ser.write(str.encode("AT"+"\r\n"))
    time.sleep(1)
    out=''
    while True:
        out += ser.read(1)
        print (out)        

    ser.close()

if __name__ == '__main__':
    serial_def()
    
    

Re: "Can only concatenate str (not "bytes") to str"

Verfasst: Dienstag 11. Oktober 2022, 16:45
von __deets__
Die Meldung kann man auch googeln, dann findet man eine ganze Menge von Antworten. Aber eine mehr schadet ja auch nicht. Von der seriellen Schnittstelle bekommst du Bytes. Das sind eine Reihe von Werten von 0-255. 8Bit/Byte eben. Und jetzt willst du das mit einem String verkbinden, bei dem jedes Zeichen eines von zehn- oder hunderttausenden aus den Schriftzeichen, Sonderzeichen, Zahlen, Emojiis und was nicht der ganzen Welt sein kann. Das geht halt nicht. Die Bytes muessen erst einem encoding entsprechend in einen String gewandelt werden. Fuer dich reicht das encoding "ascii". Also

Code: Alles auswählen

ser.read(1).decode("ascii")
Ein paar weitere Anmerkungen: der Name "serial_def" ist komisch, def steht doch schon davor. Die ganzen Argumente an das Serial-Objekt kann man im Konstruktor uebergeben (oder auch sein lassen, weil alles zur Paritaet, Bitanzahl, Stopbits eh per default schon richtig sind, siehe https://pyserial.readthedocs.io/en/late ... ial.Serial - damit entfaellt dann auch das open. Das ist dann schon open. Und nach dem open kann das auch nicht nicht open sein. Das 'isOpen' ist also cargo-cultiger Quatsch. Das zusammenpropeln des AT-Kommandos aus zwei Strings ist auch ueberkompliziert, warum nicht "AT\r\n"?

Edit: narpfels Anmerkung eingebaut, decode benutzt.

Re: "Can only concatenate str (not "bytes") to str"

Verfasst: Dienstag 11. Oktober 2022, 17:04
von narpfel
Kleiner Flüchtigkeitsfehler bei __deets__: Von `bytes` nach `str` muss man natürlich dekodieren, nicht enkodieren:

Code: Alles auswählen

ser.read(1).decode("ascii")
Außerdem: Methoden ruft man normalerweise auf einem Objekt auf, also

Code: Alles auswählen

"AT\r\n".encode()
statt

Code: Alles auswählen

str.encode("AT\r\n")
Wobei man hier auch einfacher ein `bytes`-Literal benutzen kann:

Code: Alles auswählen

b"AT\r\n"
Edit: Name korrigiert, ich kann anscheinend nicht lesen. :shock:

Re: "Can only concatenate str (not "bytes") to str"

Verfasst: Dienstag 11. Oktober 2022, 17:20
von fcutim
narpfel hat geschrieben: Dienstag 11. Oktober 2022, 17:04
Außerdem: Methoden ruft man normalerweise auf einem Objekt auf, also

Code: Alles auswählen

"AT\r\n".encode()
statt

Code: Alles auswählen

str.encode("AT\r\n")
Hab jetzt deine Variante ausprobiert, und es kommt immer noch die selbe Nachricht. Mach ich irgendwie etwas falsch oder liegts doch am Code?

Re: "Can only concatenate str (not "bytes") to str"

Verfasst: Dienstag 11. Oktober 2022, 17:26
von __deets__
Bitte den jetztigen Code zeigen. Und die vollstaendige Fehlermeldung. Die zitierten Aenderungen sind im uebrigen "Kosmetik", wenn auch natuerlich richtig. Aber reichen nicht, um den Fehler zu beheben. Dazu muss schon dekodiert werden, wie ich (und narpfel) es zeigen.

Re: "Can only concatenate str (not "bytes") to str"

Verfasst: Dienstag 11. Oktober 2022, 17:29
von fcutim

Code: Alles auswählen


import serial, time
def serial_def():
    ser = serial.Serial()
    ser.port = "COM7"
    ser.baudrate = 9600
    ser.bytesize = serial.EIGHTBITS
    ser.parity = serial.PARITY_NONE
    ser.stopbits = serial.STOPBITS_ONE
    ser.timeout = 2
    ser.xonxoff = False
    ser.rtscts = False
    ser.dsrdtr = False
    ser.write_timeout = 2
    ser.open()

    if ser.isOpen():
        print(ser.name + ' is open')

    ser.write("AT"+"\r\n".encode())
    time.sleep(1)
    out='' 
    while True:
        out += ser.read(1).decode("ascii")
        print (out)

    ser.close()

if name == 'main':
    serial_def()

Fehler Meldung:

Code: Alles auswählen


Traceback (most recent call last):
  File "c:\Users\Tim\Desktop\GSM\main.py", line 29, in <module>
    serial_def()
  File "c:\Users\Tim\Desktop\GSM\main.py", line 19, in serial_def
    ser.write("AT"+"\r\n".encode())
TypeError: can only concatenate str (not "bytes") to str

Hoffe ich hab das so richtig verstanden, wie ihr das meintet.

Re: "Can only concatenate str (not "bytes") to str"

Verfasst: Dienstag 11. Oktober 2022, 17:33
von narpfel
@fcutim: Naja, das ist jetzt der gleiche Fehler, der vorher in der Zeile mit dem `out += ...` aufgetreten ist, an einer anderen Stelle. Der Code, den du zeigst, passt übrigens nicht zur Fehlermeldung. Bitte achte darauf, den tatsächlichen Code zu zeigen, nicht irgendwas, was so ähnlich ist.

Re: "Can only concatenate str (not "bytes") to str"

Verfasst: Dienstag 11. Oktober 2022, 17:34
von fcutim
Wärst du so lieb und schreibst mir das fix um? Ich denke mal das ich zu doof dazu bin :lol:

Re: "Can only concatenate str (not "bytes") to str"

Verfasst: Dienstag 11. Oktober 2022, 17:39
von Sirius3
Benutze keine kryptischen Abkürzungen. Was soll `def` bei `serial_def` denn bedeuten? `ser` ist auch komisch? Die ganzen Einstellungen kann man gleich bei der Initalisierung angeben, und muß sie nicht nachträglich setzen. Defaultwerte muß man nicht unbedingt setzen.
Der Aufruf von open ist damit überflüssig und es ist garantiert, dass der Port offen ist, ein isOpen-Aufruf ist damit genauso überflüssig, vor allem, weil auch im False-Fall Du so weiter machst, als ob der Port offen ist.
encode ruft man auf einem String-Objekt auf, und nicht über die Klasse. Wobei hier am besten gleich mit literalen Bytes gearbeitet wird.
Man benutzt with.

Code: Alles auswählen

import serial, time

def communicate():
    with serial.Serial(
        port="COM7",
        baudrate=9600,
        timeout=2,
        write_timeout=2
    )  as port:
        port.write(b"AT\r\n")
        time.sleep(1)
        out = b''
        while True:
            out += port.read(1)
            print(out)

if __name__ == '__main__':
    communicate()

Re: "Can only concatenate str (not "bytes") to str"

Verfasst: Dienstag 11. Oktober 2022, 17:41
von fcutim
Vielen Dank! Aber jetzt kommt ein kleines Problem...

Code: Alles auswählen

NameError: name 'name' is not defined

Re: "Can only concatenate str (not "bytes") to str"

Verfasst: Dienstag 11. Oktober 2022, 17:58
von Sirius3
Und schon wieder eine verstümmelte Fehlermeldung ohne den passenden Code dazu...

Re: "Can only concatenate str (not "bytes") to str"

Verfasst: Dienstag 11. Oktober 2022, 17:59
von fcutim
Du hast doch gerade eben selbst den Code reingeschickt... Dann brauch ich ihn doch nicht noch einmal reinschicken.

Edit: Habs jetzt selbst herausgefunden.

Re: "Can only concatenate str (not "bytes") to str"

Verfasst: Dienstag 11. Oktober 2022, 18:02
von __deets__
Da in Sirius3 Code name nicht vorkommt, hast du offensichtlich was verbockt. Und darum solltest du den Code zeigen. Musst du aber natürlich nicht, kann dir halt dann keiner helfen.

Re: "Can only concatenate str (not "bytes") to str"

Verfasst: Dienstag 11. Oktober 2022, 18:03
von fcutim
Guck den Edit von meinem Kommentar auf die Antwort von Sirius3, dann weißt du Bescheid. 8)

Re: "Can only concatenate str (not "bytes") to str"

Verfasst: Dienstag 11. Oktober 2022, 18:40
von __blackjack__
@fcutim: `out` ist ein komischer Name für Daten die *rein* kommen. Ich würde da aus Effizienzgründen auch eher ein `bytearray` verwenden statt `bytes`. Das kann nämlich tatsächlich um neue Daten erweitert werden.

Dann sollte entweder das `write_timeout` nicht sein, oder da gehört noch Code hin der auf diesen Fall auch sinnvoll reagiert.

Beim `timeout` bin ich mir nicht sicher ob Du das verhalten wirklich haben willst, oder warum Du das gesetzt hast‽ Die ist klar welchen Effekt das bei dem vorhanden Code hat, und das soll auch so sein?

Zwischenstand:

Code: Alles auswählen

def communicate():
    with serial.Serial(port="COM7", timeout=2) as port:
        port.write(b"AT\r\n")
        time.sleep(1)
        buffer = bytearray()
        while True:
            buffer += port.read(1)
            print(buffer)