Sonderzeichen im string

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
Revoluzer
User
Beiträge: 3
Registriert: Donnerstag 4. August 2011, 15:15

Hallo allerseits,

ich darf mich seit gestern mit Python beschäftigen und darin ein kleines Programm schreiben. Bisher hab ich nur C++ gelernt, aber man findet sich zum Glück relativ schnell zurecht.
Bevor ich zu meinem Problem komm, will ich euch erstmal die Aufgabenstellung beschreiben.

Zusammengefasst: Dass Programm soll aus einer Excel Tabelle USt-IDs auslesen und überprüfen. Die Überprüfung läuft Online über eine XML Schnittstelle (siehe: http://evatr.bff-online.de/eVatR/xmlrpc/)
Das klappt soweit auch wunderbar, jedoch habe ich das Problem, dass sobald Sonderzeichen im Namen der Firma oder in der Adresse drinnen sind, das Programm Fehlermeldungen ausspuckt. Ich hab mich da auch schonmal informiert und bin dazu gekommen, dass es wohl an dem Unicode string liegt.

Jetzt ist meine Frage: Was muss ich an meinem Code ändern damit das Problem nicht mehr auftritt?

Vielen Dank für eure Hilfe :)

Ergänzung: Das Problem liegt nicht an der Übertragung zum Server, da sind die Sonderzeichen (sind in meinem Fall sowas wie ß,ö,ä,ü,á,à,ê, aber auch bei ,.(also Punkt und Komma)) ok, sondern wenn der Hash der zurück kommt aufbereitet werden soll...

Code: Alles auswählen

import xmlrpclib

server_url = 'http://evatr.bff-online.de/' # 'https://...' bei SSL-Verschlüsselung
server     = xmlrpclib.Server(server_url)

# Tabelle öffnen
from xlrd import open_workbook,XL_CELL_TEXT

book = open_workbook('nurUSt-ID.xls')
sheet = book.sheet_by_index(0)


# Ende der Tabelle finden
j = 0
while True:
    j = j+1
    a = sheet.cell_value(j,0)
    if a == 'ENDE':
        print 'Es werden', j ,'USt-IDs geprüft'
        break


for i in range(1,j,1):
#daten zum testen 
    UstId_2    = sheet.cell_value(i,26)
    if UstId_2[:2] == 'DE':
        UstId_1 = '0'
    else: UstId_1    = 'DE123456789'
    Firmenname = sheet.cell_value(i,7)
    Ort        = sheet.cell_value(i,14)
#PLZ vorbereiten, da als Zahl erkannt und dann immer 12345.0 rauskommt
    PLZ       = sheet.cell_value(i,12)      #Aus Tabelle auslesen
    PLZ       = str (PLZ)                   #In String umwandeln
    PLZ       = PLZ[:-2]                    #.0 abschneiden 
    Strasse   = sheet.cell_value(i,10)
    Druck     = 'nein'

    rpc = server.evatrRPC(UstId_1, UstId_2, Firmenname, Ort, PLZ, Strasse, Druck)

    #print rpc
    rpc = xmlrpclib.loads(rpc)
    rpc = rpc[0]
    t = {}
    for item in rpc:
        t[item[0]] = item[1]
    
    if t['ErrorCode'] == '200':
        print t['Firmenname']
        print 'Die angefragte USt-IdNr. ist gültig.'
        print
    elif t['ErrorCode'] == '201':
        print t['Firmenname']
        print 'Die angefragte USt-IdNr. ist ungültig.'
        print
    elif t['ErrorCode'] == '202':
        print t['Firmenname']
        print 'Die angefragte USt-IdNr. ist ungültig. Sie ist nicht in der Unternehmerdatei des betreffenden EU-Mitgliedstaates registriert.'
        print
    elif t['ErrorCode'] == '203':
        print t['Firmenname']
        print 'Die angefragte USt-IdNr. ist ungültig. Sie ist erst ab dem ',t['Gueltig_ab'],' gültig.' 
        print
    elif t['ErrorCode'] == '204':
        print t['Firmenname']
        print 'Die angefragte USt-IdNr. ist ungültig. Sie war im Zeitraum von ',t['Gueltig_ab'],' bis' ,t['Gueltig_bis'],' gültig.'
        print
    elif t['ErrorCode'] == '205':
        print t['Firmenname']
        print 'Ihre Anfrage kann derzeit durch den angefragten EU-Mitgliedstaat oder aus anderen Gründen nicht beantwortet werden. Bitte versuchen Sie es später noch einmal. Bei wiederholten Problemen wenden Sie sich bitte an das Bundeszentralamt für Steuern - Dienstsitz Saarlouis.'
        print
    elif t['ErrorCode'] == '206':
        print t['Firmenname']
        print 'Ihre deutsche USt-IdNr. ist ungültig. Eine Bestätigungsanfrage ist daher nicht möglich. Den Grund hierfür können Sie beim Bundeszentralamt für Steuern - Dienstsitz Saarlouis - erfragen.'
        print
    elif t['ErrorCode'] == '207':
        print t['Firmenname']
        print 'Ihnen wurde die deutsche USt-IdNr. ausschliesslich zu Zwecken der Besteuerung des innergemeinschaftlichen Erwerbs erteilt. Sie sind somit nicht berechtigt, Bestätigungsanfragen zu stellen.'
        print
    elif t['ErrorCode'] == '208':
        print t['Firmenname']
        print 'Für die von Ihnen angefragte USt-IdNr. läuft gerade eine Anfrage von einem anderen Nutzer. Eine Bearbeitung ist daher nicht möglich. Bitte versuchen Sie es später noch einmal.'
        print
    elif t['ErrorCode'] == '209':
        print t['Firmenname']
        print 'Die angefragte USt-IdNr. ist ungültig. Sie entspricht nicht dem Aufbau der für diesen EU-Mitgliedstaat gilt.'
        print
    elif t['ErrorCode'] == '210':
        print t['Firmenname']
        print 'Die angefragte USt-IdNr. ist ungültig. Sie entspricht nicht den Prüfziffernregeln die für diesen EU-Mitgliedstaat gelten.'
        print
    elif t['ErrorCode'] == '211':
        print t['Firmenname']
        print 'Die Abfrage einer deutschen USt-IdNr. ist nicht möglich.'
        print
    elif t['ErrorCode'] == '212':
        print t['Firmenname']
        print 'Die angefragte USt-IdNr. ist ungültig. Sie enthält ein unzulässiges Länderkennzeichen.'
        print
    elif t['ErrorCode'] == '213':
        print t['Firmenname']
        print 'Die Abfrage einer deutschen USt-IdNr. ist nicht möglich.'
        print
    #elif t['ErrorCode'] == '214':
     #   print 'Ihre deutsche USt-IdNr. ist fehlerhaft. Sie beginnt mit DE gefolgt von 9 Ziffern.'
    elif t['ErrorCode'] == '215':
        print t['Firmenname']
        print 'Ihre Anfrage enthält nicht alle notwendigen Angaben für eine einfache Bestätigungsanfrage (Ihre deutsche USt-IdNr. und die ausl. USt-IdNr.). Ihre Anfrage kann deshalb nicht bearbeitet werden.'
        print
    elif t['ErrorCode'] == '216':
        print t['Firmenname']
        print 'Ihre Anfrage enthält nicht alle notwendigen Angaben für eine qualifizierte Bestätigungsanfrage (Ihre deutsche USt-IdNr., die ausl. USt-IdNr., Firmenname einschl. Rechtsform und Ort). Es wurde eine einfache Bestätigungsanfrage durchgeführt mit folgenden Ergebnis: Die angefragte USt-IdNr. ist gültig. '
        print
    elif t['ErrorCode'] == '217':
        print t['Firmenname']
        print 'Bei der Verarbeitung der Daten aus dem angefragten EU-Mitgliedstaat ist ein Fehler aufgetreten. Ihre Anfrage kann deshalb nicht bearbeitet werden.'
        print
    elif t['ErrorCode'] == '218':
        print t['Firmenname']
        print 'Eine qualifizierte Bestätigung ist zur Zeit nicht möglich. Es wurde eine einfache Bestätigungsanfrage mit folgendem Ergebnis durchgeführt: Die angefragte USt-IdNr. ist gültig.'
        print
    elif t['ErrorCode'] == '219':
        print t['Firmenname']
        print 'Bei der Durchführung der qualifizierten Bestätigungsanfrage ist ein Fehler aufgetreten. Es wurde eine einfache Bestätigungsanfrage mit folgendem Ergebnis durchgeführt: Die angefragte USt-IdNr. ist gültig.'
        print
    elif t['ErrorCode'] == '220':
        print t['Firmenname']
        print 'Bei der Anforderung der amtlichen Bestätigungsmitteilung ist ein Fehler aufgetreten. Sie werden kein Schreiben erhalten.'
        print
    elif t['ErrorCode'] == '999':
        print t['Firmenname']
        print 'Eine Bearbeitung Ihrer Anfrage ist zurzeit nicht möglich. Bitte versuchen Sie es später noch einmal.'
        print

Edit:
Hier ist noch die Fehlermeldung:
Traceback (most recent call last):
File "C:\Users\Benutzer\Desktop\Python Zeugs\fertig\USt-ID prüfen fertig.py", line 43, in <module>
rpc = xmlrpclib.loads(rpc)
File "C:\Python27\lib\xmlrpclib.py", line 1135, in loads
p.feed(data)
File "C:\Python27\lib\xmlrpclib.py", line 557, in feed
self._parser.Parse(data, 0)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xdf' in position 1917: ordinal not in range(128)
Zuletzt geändert von Revoluzer am Freitag 5. August 2011, 08:10, insgesamt 2-mal geändert.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Ich steige durch den Code nicht so ganz durch, aber ein erstes Indiz für Probleme ist schon mal, dass keine "richtigen" Strings im Unicode-Format benutzt werden, sondern nur Byte-Arrays (das, was Python 2.x als "str" bezeichnet). Das Beispiel auf http://evatr.bff-online.de/eVatR/xmlrpc/python ist da auch nicht besser und benutzt "ss" statt "ß".

Wenn ich da ein "ß" eingebe, kommt auch ein "ß" zurück. Wenn ich die Strings alle mit "u" prefixe, um daraus richtige Unicode-Strings zu machen, funktioniert das Beispiel immer noch und daher wäre mein Tipp genau solche Strings zu benutzen. Ein solcher String kommt auch als Antwort in rpc zurück.

Offenbar ist aber xmlrpclib.loads() nicht in der Lage, so einen String zu verarbeiten. Die Doku http://docs.python.org/library/xmlrpcli ... clib.loads sagt nix dazu, also zeigt ein Trial & Error, dass da ein Byte-Array erwartet wird, also z.B:

obj = xmlrpclib.loads(rpc.encode("utf-8"))

Dann sollte es auch klappen.

Stefan
deets

@Revoluzzer

Ich verstehe nicht, was das xmlrpclib.loads soll. Das hat da nichts verloren - die Antwort, die du vom Server bekommst, ist schon im "python-format". xmlrpclib.loads brauchst du nur, wenn du haendisch mittels zb der urllib2 selbst HTTP-POST-requests gegen einen XMLRPC-Server machst. Tust du aber ja nicht.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

deets hat geschrieben:@Revoluzzer

Ich verstehe nicht, was das xmlrpclib.loads soll. Das hat da nichts verloren - die Antwort, die du vom Server bekommst, ist schon im "python-format". xmlrpclib.loads brauchst du nur, wenn du haendisch mittels zb der urllib2 selbst HTTP-POST-requests gegen einen XMLRPC-Server machst. Tust du aber ja nicht.
Ne, ne, die Antwort vom Finanzamt ist tatsächlich ein Unicode-String - warum auch immer. Siehe die von mit zitierte URL mit dem Python-Beispiel.

Stefan
deets

@Stefan

Aber das ist doch genau gut so, dass sie das ist - alles andere waere ja auch komisch. XMLRPC basiert ja auf XML, und damit hat es implizit ein encoding. Also ist was auch immer an strings in dem Ding steckt (gueltigkeit vorraussgesetzt) schon nach dem parsen des XML-bodies alles in unicode. Wie es sein soll.

Ich glaube der gute Revoluzzer hat einfach ein bisschen rumgespielt, und dachte nach dem server-call muss man nochmal etwas mit loads machen. Aber das stimmt ja nicht.
Revoluzer
User
Beiträge: 3
Registriert: Donnerstag 4. August 2011, 15:15

Erstmal danke für eure Beiträge.
Ich hab mal eure Vorschläge ausprobieren und ich musste wirklich nur

Code: Alles auswählen

rpc = xmlrpclib.loads(rpc)
durch

Code: Alles auswählen

rpc = xmlrpclib.loads(rpc.encode("utf-8"))
ersetzen.

Auch gestehen muss ich, dass ich gar nicht genau weiß was "xmlrpclib.loads" macht, sondern dass ich mich von dieser Seite (http://blog.bmussler.de/a/bestaetigung- ... telle.html) inspirieren lassen hab ;) Da des soweit funktioniert hat, hab ich das nicht weiter hinterfragt.

Soo, dann nochmal vielen Dank für eure Hilfe :)

Edit:
Hab ihr vielleicht noch eine Idee wie man das Ende der Excel-Tabelle besser abfragen kann?
Im Moment muss man noch manuell ein "ENDE" in der 1. Spalte als letzte Zeile einfügen. Im Normalfall endet die Tabelle aber einfach mit dem letzten Datensatz. Wenn ich jetzt aber die erste leere Zeile abfragen will, dann sagt er immer
IndexError: list index out of range
deets

Also, ich habe mir das nochmal angeschaut, und ein bisschen debuggt. Es ist wirklich unfassbar, aber *das* hier kommt zurueck:

Code: Alles auswählen

"<?xml version='1.0'?>\n<methodResponse>\n<params>\n<param>\n<value><string><params>\n<param>\n<value><array><data>\n<value><string>UstId_1</string></value>\n<value><string>DE123456789</string></value>\n</data></array></value>\n</param>\n<param>\n<value><array><data>\n<value><string>ErrorCode</string></value>\n<value><string>212</string></value>\n</data></array></value>\n</param>\n<param>\n<value><array><data>\n<value><string>UstId_2</string></value>\n<value><string>AB123456789012</string></value>\n</data></array></value>\n</param>\n<param>\n<value><array><data>\n<value><string>Druck</string></value>\n<value><string>nein</string></value>\n</data></array></value&g"
Die schicken via XMLRCP einen String zurueck, der XMLRPC-encodiert ist. Das muss eigentlich ein Bug sein, denn wenn es by Design ist...

@sma: dann hast du natuerlich recht, dass war mir nicht klar, wie krank das ist...
BlackJack

@Revoluzer: Ein Arbeitsblatt hat die Attribute `nrows` und `ncols`, welche die Anzahl der Zeilen beziehungsweise Spalten verraten.

Statt `range()` sollte man in Python <3 `xrange()` verwenden. Die Schrittweite ist per Voreinstellung 1, dass muss man nicht extra angeben.

Die Postleitzahl scheint in der Exceltabelle tatsächlich als Zahl hinterlegt zu sein. Das ist keine gute Idee, denn Postleitzahlen sind entgegen dem Namen keine Zahlen, sondern Zeichenfolgen. Bei einer Zahl würde ``01234 == 1234`` gelten, bei Postleitzahlen ist das aber nicht der Fall.

Die Umwandlung ist so auch ein wenig eigenartig. Statt die Zeichenkettendarstellung einer Gleitkommazahl zu manipulieren, dass sie am Ende wie eine Ganzzahl aussieht, sollte man eher die Gleitkommazahl in eine Ganzzahl umwandeln und diese dann in eine Zeichenkette. Da kann man mittels Zeichenkettenformatierung auch gleich dafür sorgen, dass sie immer fünfstellig ist und gegebenenfalls mit Nullen beginnt, damit man auch tatsächlich immer eine gültige Postleitzahl bekommt.

Namen sollte man auch nach Möglichkeit nicht an verschiedene Typen oder Arten von Informationen binden. Das betrifft `PLZ` und `rpc`.

`t` ist ein schlechter Name, da er überhaupt nichts darüber verrät was die Bedeutung des Objekts ist, welches daran gebunden ist.

Die Bedeutungen der 'ErrorCode's sollte man IMHO in einem Wörterbuch hinterlegen. Das spart eine Menge Tipparbeit für die ganzen ``if``/``elif``-Zweige. Die erste Zeile in denen ist auch immer gleich, die sollte man also davor ziehen. Ausserdem fehlt am Ende ein ``else``, dass den Fall meldet, dass ein 'ErrorCode' zurück kam, mit dem man nicht gerechnet hat.

Der Quelltext hält sich in so einigen Punkten nicht an den Style Guide for Python Code.
Revoluzer
User
Beiträge: 3
Registriert: Donnerstag 4. August 2011, 15:15

Ok viele dank für die Tipps, hab gleich mal einige umgesetzt.

Die PLZ ist in der Excel-Tabelle nicht als Zahl hinterlegt, sondern ganz normal als Text. Trotzdem wird es beim umwandeln als Zahl erkannt. Problem ist auch noch, dass das Programm europaweite PLZen aus der Tabelle holt und in manche ländern sind diese nicht 5 stellig, sondern kürzer bzw länger. Trotzdem werde ich deinen Rat befolgen und die Gleitkommazahl zuerst in ne Ganzzahl und dann in nen String umzuwandeln. Ist auf jeden Fall die elegantere Methode (wobei meine auch funktioniert ;) )
BlackJack

@Revoluzer: Wenn Du die PLZ als Zahl bekommst, dann ist die auch in der Tabelle schon als Zahl gespeichert. Das wäre auch "ganz normal", denn Tabellenkalkulationen versuchen da in der Regel schlau zu sein und alles was irgendwie geht als Zahl zu speichern, sofern man sich da nicht explizit gegen wehrt.

Wenn das international beziehungsweise mindestens europaweit funktionieren soll, dann müsstest Du da noch einmal besonders aufpassen, denn es gibt auch Länder wo dieser Postcode auch Buchstaben enthalten kann.
Antworten