Tuple Problem und Regexp

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.
facebraker
User
Beiträge: 25
Registriert: Montag 22. April 2013, 13:17

Hallo, ich bekomme von einer Webabfrage folgendes zurück:
(0, '{"status":0,"id":"c2abd058d15bf0c7f3750ab9cac6854c-1","hypotheses":[{"utterance":"TEXT","confidence":0.3940507}]}')
Ich habe rausbekommen dass es ein Tuple Datentyp ist und dachte, gut, zerlege ich ihn erst einmal:

Code: Alles auswählen

(zahl, status, id, text, score) = ret_val
bekomme ich den Fehler
ValueError: need more than 2 values to unpack/quote]

Ich verstehe den Fehler nicht :K

Das nächste Problem, ich habe mich mit Regexp gestritten :oops:
Könntet ihr mir helfen wie ich an den TEXT und den Wert von "confidence" komme? ich weiß ich könnte per Stringmanipulation durchgehen, aber
ich denke Regexp sind schicken :roll:

Danke schon mal für die Hilfe!

Gruß Alex
BlackJack

@facebraker: Bei einem Tupel mit zwei Elementen, kann man halt die Elemente schlecht auf fünf Namen verteilen.

Code: Alles auswählen

In [2]: t
Out[2]: 
(0,
 '{"status":0,"id":"c2abd058d15bf0c7f3750ab9cac6854c-1","hypotheses":[{"utterance":"TEXT","confidence":0.3940507}]}')

In [3]: len(t)
Out[3]: 2

In [4]: t[0]
Out[4]: 0

In [5]: t[1]
Out[5]: '{"status":0,"id":"c2abd058d15bf0c7f3750ab9cac6854c-1","hypotheses":[{"utterance":"TEXT","confidence":0.3940507}]}'
Da es eine Webabfrage ist, vermute ich mal ganz stark die Zeichenkette (das zweite Element) ist JSON. Dafür nimmt man keine regulären Ausdrücke sondern das `json`-Modul aus der Standardbibliothek.
facebraker
User
Beiträge: 25
Registriert: Montag 22. April 2013, 13:17

Guten Abend BlackJack,

Ich dachte die Kommas wären die Trenner :oops: ?? Stimmt die anderen Kommas sind in der Hochkommas :oops:

Ich möchte nur an "TEXT" ran und das ist auch nur eine Zeichenkette, ein String in
Anführungszeichen und an den Wert hinter confidence...
Hast du da eine Idee?

Gruß Alex
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Code: Alles auswählen

In [6]: import json

In [7]: t = (0, '{"status":0,"id":"c2abd058d15bf0c7f3750ab9cac6854c-1","hypotheses":[{"utterance":"TEXT","confidence":0.3940507}]}')

In [8]: d = json.loads(t[1])

In [9]: d
Out[9]: 
{u'hypotheses': [{u'confidence': 0.3940507, u'utterance': u'TEXT'}],
 u'id': u'c2abd058d15bf0c7f3750ab9cac6854c-1',
 u'status': 0}

In [10]: texts = [entry['utterance'] for entry in d['hypotheses']]

In [11]: texts
Out[11]: [u'TEXT']
Wahrscheinlich sollte man die Texte noch nach "confidence" sortieren, aber das lasse ich mal als Uebung offen.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

facebraker hat geschrieben:Ich möchte nur an "TEXT" ran und das ist auch nur eine Zeichenkette, ein String in
Anführungszeichen und an den Wert hinter confidence...
Das ganze sieht aus wie eine Python-Datenstruktur die sich mit literal_eval parsen lässt.

Schauen wir doch mal.

Code: Alles auswählen

>>> result = (0, '{"status":0,"id":"c2abd058d15bf0c7f3750ab9cac6854c-1","hypotheses":[{"utterance":"TEXT","confidence":0.3940507}]}')
>>> import ast
>>> data = ast.literal_eval(result[1])
>>> print data
{'status': 0, 'hypotheses': [{'confidence': 0.3940507, 'utterance': 'TEXT'}], 'id': 'c2abd058d15bf0c7f3750ab9cac6854c-1'}
>>> print data['hypotheses'][0]['utterance']
TEXT
Passt.


Edit: Im Kontext Web ist die von cofi vorgeschlagene Lösung mit JSON natürlich auch ganz prima.
facebraker
User
Beiträge: 25
Registriert: Montag 22. April 2013, 13:17

Vielen Dank cofi und /me,

Werde ich morgen gleich probieren, gebe natürlich Feedback.

Danke nochmal!

Gruß Alex
facebraker
User
Beiträge: 25
Registriert: Montag 22. April 2013, 13:17

Gutem Morgen,

ich habe es nach cofi's Anleitung gemacht.
Das ist das Problem, ich habe es als Zeichenkette gesehen und mir keine Gedanken gemacht, was da eigentlich zurück kommt.
Dumm sowas.

Code: Alles auswählen

texts = [entry['utterance'] for entry in d['hypotheses']]
scores = [entry['confidence'] for entry in d['hypotheses']]
Das war es. :mrgreen:

Ein kleines Problem habe ich noch :oops:

Das JSON Objekt codiert Umlaute als UTF-8, z.B.. ä = \xc3\xa4

Mein Plan war es, die Zeichen dann zu ersetzen

Code: Alles auswählen

.replace("\xc3\xa4","ae")
Aber sobald ich die Liste die ich habe in String umwandle werden kryptische Zeichen daraus, wie kann ich die Datentypen
noch umwandeln?

Danke Gruß Alex
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

facebraker hat geschrieben:Das JSON Objekt codiert Umlaute als UTF-8, z.B.. ä = \xc3\xa4

Code: Alles auswählen

>>> '\xc3\xa4'.decode('UTF-8')
u'\xe4'
>>> print '\xc3\xa4'.decode('UTF-8')
ä
Die Frage ist ohnehin wie die Zeichen tatsächlich im String stehen. Wie du am Beispiel siehst macht es einen Unterschied ob du die Daten oder deren Stringrepräsentation ausgibst.
Zuletzt geändert von /me am Montag 29. April 2013, 10:47, insgesamt 1-mal geändert.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Warum möchtest du die Zeichen überhaupt ersetzen? Wenn du schon weißt, dass alles UTF-8 codierst ist, dann mach aus den Strings einfach Unicode-Strings. Etwas besseres kann dir doch gar nicht passieren.
Das Leben ist wie ein Tennisball.
BlackJack

@facebraker: JSON ist in der Regel als UTF-8 kodiert. Wenn man das parst wird `unicode` daraus. Automatisch. Da dürfte es also gar kein Problem geben. Bist Du sicher, dass Du nicht irgendwo etwas falsch interpretierst?
facebraker
User
Beiträge: 25
Registriert: Montag 22. April 2013, 13:17

Hallo, ich bin mir sicher, dass ich da was falsch interpretiere. :cry:

Ich möchte mit den String weiter arbeiten, so z.B.

Code: Alles auswählen

if teil_str[0]=="Aenderung":
Ich möchte gleich die Umlaute eliminieren...
Aber ich bekomme z.T. Strings mit Umlauten von dem Service.
Also dachte ich mir ersetzt ich gleich "\xc3\x84" durch "Ae" und arbeite damit weiter.
Die Strings brauche ich für Ausgabe oder Ähnliches nicht, nur für Abprüfungen s.o.

@ /me:

funktioniert leider auch nicht:
print texts[0].decode("UTF-8")
File "/usr/lib/python2.7/encodings/utf_8.py", line 16, in decode
return codecs.utf_8_decode(input, errors, True)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe4' in position 9: ordinal not in range(128)
Gruß Alex
BlackJack

@facebraker: Das dekodieren funktioniert nicht, weil die Zeichenketten bereits dekodiert sind. Du hast da schon Unicode-Objekte vorliegen. Und wenn Du die mit Zeichenketten vergleichst die etwas ausserhalb von ASCII enthalten, dann müssen *die* auch `unicode`-Objekte sein, sonst ist nicht klar wie das verglichen werden soll. Also:

Code: Alles auswählen

if teil_str[0] == u'Änderung':
facebraker
User
Beiträge: 25
Registriert: Montag 22. April 2013, 13:17

:K
ich arbeite auf der Fedora Bash-Shell und da sind Umlaute total tabu :-( kriege ich noch nicht einmal eingegeben. (kann nicht umstellen ist ein konfigurierter Server, das Problem mit dem Change und dem running System ;-))

Ich habe folgendes getestet:

Code: Alles auswählen

teil_str = text.split()
	print teil_str
	if teil_str[u'Änderung':
		print "gefunden"
Kommt folgender Fehler:
SyntaxError: Non-ASCII character '\xc4' in file ./cmd_exec.py on line 27, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details
Wie kann ich die Zeichen so konvertieren dass ich die Umlaute weg habe und ich mit Ae Ue ae usw. arbeiten kann.
Ich trickse mich ja mit dem Unicode auf der Shell dann immer selber aus, wenn ich es nicht einmal lesen kann? :?:

Gruß Alex
BlackJack

@facebraker: Die Fehlermedlung sagt doch woran es liegt, sogar mit einem Link zu einer ausführlichen Erklärung. Wenn Du etwas ausserhalb von ASCII im *Quelltext* hast, dann musst Du mit einem speziellen Kommentar am Anfang der Datei angeben wie der Quelltext selbst kodiert ist. Denn sonst kann der Compiler nicht wissen wie er die Bytes in der Quelltextdatei interpretieren soll.
facebraker
User
Beiträge: 25
Registriert: Montag 22. April 2013, 13:17

:K
but no encoding declared;
Aber welches encoding lege ich fest?

Wie bekomme ich das Encoding meines Quelltextes heraus, ich habe irgendwie ein Knoten im Kopf.

Wenn ich festlege, der Quellcode ist Unicode, akzeptiert er es nicht.

*Bahnhof* ...

Bin total gefrustet.

Gruß Alex
facebraker
User
Beiträge: 25
Registriert: Montag 22. April 2013, 13:17

Okay:

Code: Alles auswählen

alki@localhost:~/coding$ file -i cmd_exec.py
cmd_exec.py: text/x-python; charset=iso-8859-1
Das weiß ich jetzt
Zuletzt geändert von facebraker am Montag 29. April 2013, 12:52, insgesamt 1-mal geändert.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

facebraker hat geschrieben:Wie bekomme ich das Encoding meines Quelltextes heraus, ich habe irgendwie ein Knoten im Kopf.
Das ist das Encoding in dem du die Source-Datei abspeicherst.
facebraker hat geschrieben:Wenn ich festlege, der Quellcode ist Unicode, akzeptiert er es nicht.
Der Quellcode kann nicht als "Unicode" vorliegen. Unicode ist ein Konzept, keine Codierung.

Gleiches gilt für Daten. Wenn du Daten von außen bekommst (oder nach dort gibst), dann liegen sie in irgendeiner Codierung vor. Das kann beispielsweise ASCII mit einem Byte pro Zeichen, ISO-8859-1 mit einem Byte pro Zeichen oder auch UTF-8 mit einem oder mehreren Byte pro Zeichen sein. Dieser Bytestream ist prinzipiell bedeutungslos bis du ihn nach Unicode überführst.

Im Programm arbeitest du dann mit Unicode und es kann dir völlig egal sein in welcher Form Python das intern ablegt.
Zuletzt geändert von /me am Montag 29. April 2013, 12:04, insgesamt 1-mal geändert.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Nein, Python erwartet ein coding Cookie, wenn du unicode-Literale ausserhalb von ASCII benutzt:

Code: Alles auswählen

# -*- coding: utf-8 -*-
in der ersten bzw zweiten Zeile.

(bzw die Kodierung die tatsaechlich verwendet wird).
facebraker
User
Beiträge: 25
Registriert: Montag 22. April 2013, 13:17

Okay, jetzt habe ich es gefressen:

Code: Alles auswählen

 file -i cmd_exec.py
cmd_exec.py: text/x-python; charset=iso-8859-1
Also

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: iso-8859-1 -*-
Dann funktioniert auch der Test.

Danke!

Gruß Alex
BlackJack

@facebraker: Das Problem bei Kodierungen ist, dass man die aus Daten nicht 100% zuverlässig ermitteln kann. Statt ``file`` raten zu lassen, sollte man eigentlich *wissen* in welcher Kodierung man den eigenen Quelltext abspeichert. Wenn der verwendete Editor diese Information nicht preis gibt (und einen auch wählen lässt), sollte man über einen anderen Editor nachdenken.
Antworten