Python: Ergebnis von asynchronem HTTP POST Request verarbeiten

canju

Erfahrenes Mitglied
@Sempervivum ich weiß gar nicht wie ich das wieder gut machen kann. Du leistest wirklich tolle unterstützung, tausend Dank.

Ich verwende jetzt die Variante, die die ID durch die Funktion post_async durchschleift.

Die fruit_id scheint auch tatsächlich für jeden Eintrag richtig zugeordnet zu werden:
SQL:
SELECT
    *
FROM fruits_output AS o
INNER JOIN fruits_input AS i ON o.fruit_id = i.fruit_id
WHERE 1
        #AND o.fruit_name_output != UPPER(i.fruit_name_input)

Um das auch bei längeren Scriptlaufzeiten zu bestätigen, werde ich das Script jetzt auf den Produktiv-Endpunkt umstellen, welcher mehrere 10k Anfragen stellen muss (Konnte den Testcase leider nicht mit dem Produktiv-Endpunkt bereitstellen, da interne Authorisierung verwendet wird).

Und dann sehr akribisch nochmal gegenprüfen, ob die Zuweisung weiterhin korrekt ist und dir selbstverständlich berichten.
 

canju

Erfahrenes Mitglied
Ok, habe jetzt den Produtkiv-Endpunkt mit eingebunden und bin wieder zur Version bei der die ID nicht durch die Funktion post_async durchschliffen wird.

Um beim Testcase zu bleiben habe ich die Response simuliert, so wie ich die Verschachtelung im Prod-Endpunkt bekomme:
JSON:
[
    {
        "INPUT": "ananas",
        "OUTPUT": "ANANAS",
        "OUTPUT_PROPERTIES": [
                {
                    "variety": "Cayenne-Ananas",
                    "weight": 1.5,
                    "cost": {
                        "one_piece": 3.50,
                        "ten_piece": 30.00
                    }

                },
                {
                    "variety": "Queens-Ananas",
                    "weight": 2,
                    "cost": {
                        "one_piece": 5.50,
                        "ten_piece": 45.00
                    }

                },
                {
                    "variety": "Spanish-Ananas",
                    "weight": 1.2,
                    "cost": {
                        "one_piece": 1.50,
                        "ten_piece": 10.00
                    }

                }
        ]
    }
]

Ich möchte jetzt auch die Sorten (variety) aus den OUTPUT_PROPERTIES mit erfassen, also so dass ich für die Ananas insgesamt 3 Zeilen in der Output Tabelle gespeichert bekomme:
Code:
input  | output | fruit_id | variety        | weight | cost_one_piece | cost_ten_piece
ananas | ANANAS | 1        | Cayenne-Ananas | 1.5    | 3.50           | 30.00
ananas | ANANAS | 1        | Queens-Ananas  | 2      | 5.50           | 45.00
ananas | ANANAS | 1        | Spanish-Ananas | 1.2    | 1.50           | 10.00

Daher habe ich folgende Schleife hinzugefügt:

Python:
    idx = 0
    for fruit in fruits:
        for fruit_properties in fruit['OUTPUT_PROPERTIES']:

            sql = f'''INSERT INTO {destination_table} (fruit_id, fruit_name_output, variety)
                        VALUES (%s, %s, %s)
            '''
            val = (
                # ID aus dem Record aus der Datenbank:
                str(records[idx]['fruit_id']),
                # Fruchtname aus der Antwort vom Server:
                str(fruit['OUTPUT']),
                str(fruit['variety'])
                
            )
            idx += 1

            db_config.cursor.execute(sql, val)
            db_config.connection.commit()

asyncio.get_event_loop().run_until_complete(main())

Aber bei der verschachtelten Response erhalte ich den Fehler:

Code:
...   
   str(records[idx]['fruit_id']),
IndexError: list index out of range
 

Sempervivum

Erfahrenes Mitglied
Ohne das getestet zu haben fallen mir zwei Dinge auf:
  • Dieser Index in der Variablen idx bezieht sich auf die Liste fruits, daher müsste das Erhöhen in der äußeren Schleife passieren, d. h. an das Ende und eine Stufe weiter nach links.
  • Die Varietät befindet sich auf der anderen Seite in der inneren Schleife, d. h. Du müsstest sie aus fruit_properties heraus holen.
Code:
    idx = 0
    for fruit in fruits:
        for fruit_properties in fruit['OUTPUT_PROPERTIES']:

            sql = f'''INSERT INTO {destination_table} (fruit_id, fruit_name_output, variety)
                        VALUES (%s, %s, %s)
            '''
            val = (
                # ID aus dem Record aus der Datenbank:
                str(records[idx]['fruit_id']),
                # Fruchtname aus der Antwort vom Server:
                str(fruit['OUTPUT']),
                str(fruit_properties['variety'])
            )

            db_config.cursor.execute(sql, val)
            db_config.connection.commit()
        idx += 1
 

canju

Erfahrenes Mitglied
Das hat auf Anhieb funktioniert (y)

Ich hab bei meiner simulierten Response oben vergessen mehrere OUTPUT_PROPERTIES einzufügen, die ich aus dem Prod-Endpunkt erhalte:
JSON:
[
    {
        "INPUT": "ananas",
        "OUTPUT": "ANANAS",
        "OUTPUT_PROPERTIES":
        [
            {
                "variety": "Cayenne-Ananas",
                "weight": 1.5,
                "cost":
                {
                    "one_piece": 3.50,
                    "ten_piece": 30.00
                }
            },
            {
                "variety": "Queens-Ananas",
                "weight": 2,
                "cost":
                {
                    "one_piece": 5.50,
                    "ten_piece": 45.00
                }
            },
            {
                "variety": "Spanish-Ananas",
                "weight": 1.2,
                "cost":
                {
                    "one_piece": 1.50,
                    "ten_piece": 10.00
                }
            }
        ],
        "OUTPUT_PROPERTIES":
        [
            {
                "taste": "delicious",
                "shape": "round"
            }
        ]

    }
]
Ich hänge jetzt an der STelle fest auch die zweiten Properties mit in die Datenbank zu holen, also taste und shape:
Code:
input  | output | fruit_id | variety        | weight | cost_one_piece | cost_ten_piece | taste     | shape
ananas | ANANAS | 1        | Cayenne-Ananas | 1.5    | 3.50           | 30.00          | delicious | round
ananas | ANANAS | 1        | Queens-Ananas  | 2      | 5.50           | 45.00          | delicious | round
ananas | ANANAS | 1        | Spanish-Ananas | 1.2    | 1.50           | 10.00          | delicious | round

Sodass ich jetzt diesen Fehler bekomme:
Code:
TypeError: list indices must be integers or slices, not str

Wenn ich dann diese Zeile:
Python:
for fruit_properties in fruit['OUTPUT_PROPERTIES']:
änder in:
Python:
for fruit_properties in fruit[0]['OUTPUT_PROPERTIES']:
erhalte ich zumindest die Daten aus den ersten OUTPUT_PROPERTIES
Habe dann probiert ähnlich wie die äußere Schleife mit idx2 zu arbeiten:

Python:
    idx = 0
    for fruit in fruits:
        idx2 = 0
        for fruit_properties in fruit[idx2]['OUTPUT_PROPERTIES']:

            sql = f'''INSERT INTO {destination_table} (fruit_id, fruit_name_output, variety)
                        VALUES (%s, %s, %s)
            '''
            val = (
                # ID aus dem Record aus der Datenbank:
                str(records[idx]['fruit_id']),
                # Fruchtname aus der Antwort vom Server:
                str(fruit['OUTPUT']),
                str(fruit_properties[idx2]['variety']),
                str(fruit_properties[idx2]['taste'])
            )

            db_config.cursor.execute(sql, val)
            db_config.connection.commit()
            idx2 += 1
        idx += 1

und erhalte wieder:
Python:
    ...
    str(fruit_properties[idx2]['variety']),
IndexError: list index out of range

Diesmal müsste doch zumindest die Einrückung stimmen oder nicht? :)
 

Sempervivum

Erfahrenes Mitglied
Da sehe ich zunächst mal in dem JSON ein Problem: Ein Schlüssel kann nur ein Mal auftreten. D. h. die Eigenschaften müsstest Du irgend wie integrieren, entweder für die Frucht allgemein:
Code:
[
    {
        "INPUT": "ananas",
        "OUTPUT": "ANANAS",
        "taste": "delicious",
        "shape": "round",
        "OUTPUT_PROPERTIES":
        [
            {
                "variety": "Cayenne-Ananas",
                "weight": 1.5,
                "cost":
                {
                    "one_piece": 3.50,
                    "ten_piece": 30.00
                }
            },
oder spezifisch für jede Varietät:
Code:
[
    {
        "INPUT": "ananas",
        "OUTPUT": "ANANAS",
        "OUTPUT_PROPERTIES":
        [
            {
                "variety": "Cayenne-Ananas",
                "taste": "delicious",
                "shape": "round",
                "weight": 1.5,
                "cost":
                {
                    "one_piece": 3.50,
                    "ten_piece": 30.00
                }
            },