pyodbc ValueError: hour must be in 0..23

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Benutzeravatar
sparrow
User
Beiträge: 4502
Registriert: Freitag 17. April 2009, 10:28

Ich denke nicht, dass das an dem tatsächlichen Inhalt des Feldes liegt. FKEADT ist das erste Feld in der Tabelle, das laut cursor.description die Klasse datetime.date hat. Und dahin sollte der enthaltene Wert eigentlich konvertiert werden. datetime.date kennt aber keine Stunden, weshalb es eigentlich gar nicht zu dem Fehler kommen kann.

Du könntest das Problem umgehen, indem du die entsprechenden Felder nicht mit selektierst (wie hier bereits im Thread vorgeschlagen kein * im SELECT-Statement). Das funktioniert aber nur so lange, bis du eines der Felder tatsächlich brauchst.

Warum das auf dem einen Rechner geht und auf dem anderen nicht, verstehe ich allerdings nicht. Ich hätte nämlich auf ein Problem im ODBC-Treiber getippt. Bzw. die Einstellungen, die er ggf. verwendet und aus dem System liest.
marju
User
Beiträge: 21
Registriert: Donnerstag 12. Dezember 2019, 13:26
Wohnort: Bad Pyrmont

Ich verstehe es leider auch nicht.
Die Datumsfelder benöitge ich derzeit nicht. Ich versuche es mal mit dem * im SELECT-Statement.

Vielen Danke für deine Mühe. ;-)
Benutzeravatar
sparrow
User
Beiträge: 4502
Registriert: Freitag 17. April 2009, 10:28

Nein, eben _kein_ * im SELECT-Statement. Selektier dort explizit nur die Felder, die du brauchst.
Unabhängig von dem Problem hier, ist das immer sinnvoll.
marju
User
Beiträge: 21
Registriert: Donnerstag 12. Dezember 2019, 13:26
Wohnort: Bad Pyrmont

Hatte mich falsch ausgedrückt, ich nehme nur die benötigten Spalten. Das funktioniert. ;-)
marju
User
Beiträge: 21
Registriert: Donnerstag 12. Dezember 2019, 13:26
Wohnort: Bad Pyrmont

Das Problem lässt mich leider immer noch nicht los.

Folgendes habe ich noch probiert.
Der Datensatz mit dem Datum, welches den Fehler erzeugt, steht in der AS400 wie folgt:
19.12.2019
Auf dem Rechner wo die Abfrage läuft sieht die Ausgabe wie folgt aus:
2019-12-19

Die anderen Rechner liefern den ValueError: Hours must be in 0..23
Hat jemand eine Idee dazu???
Benutzeravatar
sparrow
User
Beiträge: 4502
Registriert: Freitag 17. April 2009, 10:28

Was ist das eigentlich für eine Datenbank auf der AS400? Falls das eine Informix-Datenbank ist, könntest du einen Zugriff darüber versuchen.
marju
User
Beiträge: 21
Registriert: Donnerstag 12. Dezember 2019, 13:26
Wohnort: Bad Pyrmont

Das müsste eine DB2 sein.
Benutzeravatar
sparrow
User
Beiträge: 4502
Registriert: Freitag 17. April 2009, 10:28

Da habe ich noch nie mit gearbeitet.
Aber offensichtlich liegt das Problem ja irgendwo in der ODBC-Schnittstelle. pyodbc erkennt korrekt, dass es sich um eine Datums-Spalte handelt und möchte die nach datetime.date konvertieren. Das schlägt allerdings fehl.

Ich würde versuchen an die Rohdaten zu kommen, die tatsächlich kommen um hier vielleicht einen Unterschied zwischen den Rechnern zu sehen, auf denen es funktioniert und denen, auf denen es nicht funktioniert.

Hier wird beschrieben, wie man eine eigene Konverterfunktion in pyodbc hinterlegt. Und hier stehen die verschiedenn Datentypen, die pyodbc verwendet.

Vielleicht funktioneirt so etwas (ungetestet, musst du vielleicht ein bischen basteln):

Code: Alles auswählen

import pyodbc
import struct

def handle_date(dto_value):
    print(f"Raw data: {dto_value}")
    tup = struct.unpack("<6hI2h", dto_value)
    print(f"After unpack: {tup}")


with pyodbc.connect(
    driver='{iSeries Access ODBC Driver}',
    system='172.16.0.3',
    uid='user',
    pwd='password')as connection:
    connection.add_output_converter(pyodbc.SQL_TYPE_DATE, handle_date)
    cursor = connection.cursor()
    sql_statement = """SELECT FKEADT FROM WAWBRUDTA.FERKPU
                       WHERE FKAUNR >= '1900000' ORDER BY FKAUNR
                       LIMIT 1"""
    cursor.execute(sql_statement)
    cursor.fetchone()
Wenn das so läuft, wie ich mir das vostelle, wird die Konverfunktion für datetime.date ersetzt und mit etwas Glück das ausgegeben, was vor der Konvertierung kommt.
marju
User
Beiträge: 21
Registriert: Donnerstag 12. Dezember 2019, 13:26
Wohnort: Bad Pyrmont

Danke für die Info.
Ich werde das mal probieren.
Wünsche auf diesem Weg ein frohes Fest und guten Rutsch.
Antworten