Variablentyp umwandeln.

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.
Antworten
RIN67630
User
Beiträge: 91
Registriert: Sonntag 29. April 2018, 08:07

Aller Anfang ist schwer. Auch mit Python.

Als C++ hardwarenaher Programmierer tue ich mich mit Python schwer.
Komplexes kann verbüffend kompakt geschrieben werden, aber ich bin an klar definierten Variablentypen gewöhnt und hier komme ich mit dem Durcheinander nicht klar.

Erschwerend kommt dazu, dass die Handbücher fast ausschließlich objektorientiertes Fachjargon nutzen, so dass selbst einfache Anleitungen kaum zu vestehen sind.

Konkret:
Wie wandle ich eine Float-Variable in einem Byte? Wie umgekehrt?
Das gleiche mit einem uint32? oder ein int32?
Wie lasse ich eine Float-Variable in einem Ascii String formatiert umwandeln?
Gibt es sowas, wie die sprintf() Methode?

Wo kann ich dafür eine Anleitung finden (deutsch ,englisch, französisch, aber keine mit jedes 2 Wort als Fachkauderwelsch)
Gibt es das?
Danke
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

RIN67630 hat geschrieben:Wie wandle ich eine Float-Variable in einem Byte? Wie umgekehrt?
Das gleiche mit einem uint32? oder ein int32?
Schau dir hierfür mal das struct-Modul an.
RIN67630 hat geschrieben:Wie lasse ich eine Float-Variable in einem Ascii String formatiert umwandeln?
Gibt es sowas, wie die sprintf() Methode?
Auch Python beherrscht String Formatting. Zum einen via str.format(), zum anderen mit dem %-Operator. Wobei letzteres deutlich näher an der C-typischen Syntax ist. Eine ganz gute Einführung, die beide Arten (d.h. pythonisch und klassisch) beschreibt, findest du hier.
RIN67630
User
Beiträge: 91
Registriert: Sonntag 29. April 2018, 08:07

[quote="snafu"]
Schau dir hierfür mal das struct-Modul an.

Getan. Ausprobiert. Kein Erfog:

Code: Alles auswählen

>>> dB = 45.3
>>> print dB
45.3
>>> dB = dB // 1
>>> print dB
45.0
>>> from struct import *
>>> pack ('c',dB)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
struct.error: char format require string of length 1
ich kann in dB das schreiben was ich will aus pack() kommt immer das gleiches heraus.

Es muss doch nicht so kompliziert und unituitiv sein, sowas einfaches, wie ein Float, das >0 und <255 ist, als Byte zu konvertieren!
im Arduino Compiler schreibe ich:
x = byte(dB); //fertig!
Hier bin ich seit Stunden am Suchen...
RIN67630
User
Beiträge: 91
Registriert: Sonntag 29. April 2018, 08:07

So ich bin das Problem ausgewichen.
Die Ursprungsformel hatte wegen eine Multiplikation mit 0.1 das Ergebnis ins Königreich der Floats katapultiert.
Ich habe die Multiplikation * 0.1 durch eine Division / 10 ersetzt. Jetzt kommt ein Integer heraus...
Mei ist das gewöhnungsbedürftig!

Nur habe ich ein Integer, aber noch kein Byte.
Das ist das nächstes Problem. Mit der socket Library muss ich ein Byte (nicht 2) an einem Socket senden.

Wenn ich jetzt s.send(dB) durchführe, schickt er eifrig zwei Bytes heraus!

Hat jemand eine Idée?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

RIN67630 hat geschrieben:Die Ursprungsformel hatte wegen eine Multiplikation mit 0.1 das Ergebnis ins Königreich der Floats katapultiert.
Ich habe die Multiplikation * 0.1 durch eine Division / 10 ersetzt. Jetzt kommt ein Integer heraus...
Mei ist das gewöhnungsbedürftig!
Das Verhalten ist bei C++ dasselbe.
RIN67630 hat geschrieben:Nur habe ich ein Integer, aber noch kein Byte.
Die Lösung dafür wurde schon oben genannt.
Das Leben ist wie ein Tennisball.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

RIN67630 hat geschrieben:Es muss doch nicht so kompliziert und unituitiv sein, sowas einfaches, wie ein Float, das >0 und <255 ist, als Byte zu konvertieren!
im Arduino Compiler schreibe ich:
x = byte(dB); //fertig!
Hier bin ich seit Stunden am Suchen...
Python verfolgt eben ein anderes Konzept. Da denkt man in Zahlen und nicht in Shorts, Bytes und Longs. Das ist an den Schnittstellen zur "C-Welt" manchmal etwas frickelig, wobei es oft Bibliotheken gibt, die einem die Umwandlungen abnehmen. Man müsste die nur benutzen.

Und dafür, dass du so vernarrt in Typen bist, stellst du dich im Umgang mit dem pack()-Aufruf nicht allzu geschickt an... ;)
Benutzeravatar
noisefloor
User
Beiträge: 3843
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

@RIN67630: dein Grundproblem ist, dass du _denkst_, du müsstest in Python alles so machen wie in C++. Das ist falsch (also so gut wie immer, wenn du von Sprache A auf B wechselst). Wenn du ideomatisches Python schreiben willst, musst du den Ideomen von Python folgen und die von C++ vergessen.

Gruß, noisefloor
RIN67630
User
Beiträge: 91
Registriert: Sonntag 29. April 2018, 08:07

snafu hat geschrieben: Und dafür, dass du so vernarrt in Typen bist, stellst du dich im Umgang mit dem pack()-Aufruf nicht allzu geschickt an... ;)
Ich gebe gern zu, dass ich immer noch nicht verstanden habe, wie man damit einen Byte erzeugt. :oops:

Nein, ich bin nicht im "Byte" Typ vernarrt, ich muss* der Gegenstelle (auf der ich leider keinen Einfluss habe) exakt einen Byte liefern.
Vielleicht gibt es eine andere Abhilfe im Socket-Modul? Ich bin am Suchen...

* das ist übrigens die Definition des schlechten Streßes: etwas zu müssen und es nicht zu können.
Verzeiht mir bitte, wenn ich etwas gereizt bin.
Benutzeravatar
noisefloor
User
Beiträge: 3843
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

Integer haben in Python auch eine `to_bytes`Methode, mit der du einen Integer-Wert in Bytes umwandeln kannst. Doku.

Gruß, noisefloor
RIN67630
User
Beiträge: 91
Registriert: Sonntag 29. April 2018, 08:07

noisefloor hat geschrieben:Hallo,
Integer haben in Python auch eine `to_bytes`Methode, mit der du einen Integer-Wert in Bytes umwandeln kannst. Doku.
Danke" Das klingt gut: gleich ausprobiert:

Code: Alles auswählen

>>> (250).to_bytes(1, byteorder='big')
Traceback (most recent call last):   File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute 'to_bytes'
Aber der Grund habe ich auch gefunden: Python 2.7.13 (default, Nov 24 2017, 17:33:09)
Also erstmals die neue Version für Raspberry Pi kompilieren?
Vielleicht gibt es ein Grund, warum sie nicht in den Raspbian Repos ist?
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du solltest das installieren können. Einen technischen Grund warum das nicht laufen sollte gibt es obendrauf auch nicht.

Was an

Code: Alles auswählen

>>> import struct
>>> struct.pack("b", 127)
b'\x7f'
nun aber so irre kompliziert sein soll erschließt sich mir nicht :K
Benutzeravatar
noisefloor
User
Beiträge: 3843
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

Python 3 ist auch unter Raspbian Teil der Grundinstallation. Falls wider erwarten nicht:

Code: Alles auswählen

sudo apt install python3
Du musst - wie bei den allermeisten anderen Linux-Distros auch - Python 3 über `python3` aufrufen. `python` startet immer Python 2.

Falls du nicht einen sehr guten Grund hast, Python 2 heutzutage noch zu nutzen, solltest du sowie so mit Python 3 arbeiten.

Gruß, noisefloor
Benutzeravatar
Kebap
User
Beiträge: 686
Registriert: Dienstag 15. November 2011, 14:20
Wohnort: Dortmund

RIN67630 hat geschrieben:Vielleicht gibt es ein Grund, warum sie nicht in den Raspbian Repos ist?
Der Grund ist, dass die Umstellung von Python 2 auf 3 über mehrere Jahre voran geht und immer noch andauert, weil manche Programme nicht 100% kompatibel sind.
MorgenGrauen: 1 Welt, 8 Rassen, 13 Gilden, >250 Abenteuer, >5000 Waffen & Rüstungen,
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
RIN67630
User
Beiträge: 91
Registriert: Sonntag 29. April 2018, 08:07

noisefloor hat geschrieben: Du musst - wie bei den allermeisten anderen Linux-Distros auch - Python 3 über `python3` aufrufen. `python` startet immer Python 2.
[Stirnklopf] läuft auch OoB!
Manchmal fehlt einem nur der entscheidender Hinweis!
Danke.

P.S. struct.pack("B",20) habe ich jetzt auch verstanden.
#"B", nicht "b", wenn man unsigned Byte möchte
Es kommt ein Byte heraus. Dargestellt wird aber immer ASCII, sofern es darstellbar ist.
Aber zum Weiterleiten an Socket, ist die Python-Darstellung irrelevant.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

RIN67630 hat geschrieben:Es kommt ein Byte heraus. Dargestellt wird aber immer ASCII, sofern es darstellbar ist.
Aber zum Weiterleiten an Socket, ist die Python-Darstellung irrelevant.
Ah, okay. Dich hatte verwirrt, dass da keine Zahl steht, sondern ein Zeichen. Das ist quasi die Art von Darstellung, die man bei einem Binärformat auch in der jeweiligen Datei hätte, wenn man sie in einem Editor öffnet. Dein Socket lauscht aber eh nur auf die "Morsezeichen" (Bits). Was man daraus macht, ist abhängig vom Kontext.
RIN67630
User
Beiträge: 91
Registriert: Sonntag 29. April 2018, 08:07

snafu hat geschrieben:Dich hatte verwirrt, dass da keine Zahl steht, sondern ein Zeichen.
Übrigens, nicht nur!
Den ersten Versuch machte ich, Deiner Empfehlung nach, als die Eingangsvariable noch ein Float war. Das ging grundsätzlich schief.
Antworten