Einfache Python-Methode, deren Ausführung / Ausführung ewig dauert

8

Mein Code bleibt bei der clean_up()Methode in hängenMyClass()

my_class.py:

import os
import pandas as pd
import psycopg2, pymysql, pyodbc
from db_credentials_dict import db_credentials

class MyClass():

    def __init__(self, from_database, to_table_name, report_name):
        ...

    def get_sql(self):
        ...

    def get_connection(self):
        ...

    def query_to_csv(self):
        ...

    def csv_to_postgres(self):
        ...

    def extract_and_load(self):
        self.query_to_csv()
        self.csv_to_postgres()

    def get_final_sql(self):
        ...

    def postgres_to_csv(self):
        ...

    def clean_up(self):
        print('\nTruncating {}...'.format(self.to_table_name), end='')
        with self.postgres_connection.cursor() as cursor:
            cursor.execute("SELECT NOT EXISTS (SELECT 1 FROM %s)" % self.to_table_name)
            empty = cursor.fetchone()[0]
            if not empty:
                cursor.execute("TRUNCATE TABLE %s" % self.to_table_name)
        self.postgres_connection.commit()
        print('DONE')

        print('Removing {}...'.format(self.filename), end='')
        if os.path.exists(self.filepath):
            os.remove(self.filepath)
            print('DONE')
        else:
            print('{} does not exist'.format(self.filename))

main.py:

from my_class import MyClass
from time import sleep

bookings = MyClass(from_database='...',to_table_name='...',report_name='...')
bookings2 = MyClass(from_database='...',to_table_name='...',report_name='...')
channel = MyClass(from_database='...',to_table_name='...',report_name='...')
cost = MyClass(from_database='...',to_table_name='...',report_name='...')

tables = [bookings, bookings2, channel, cost]
for table in tables:
    table.extract_and_load()

daily_report = MyClass(from_database='...',to_table_name='...',report_name='...')
daily_report.postgres_to_csv()
sleep(10)

for table in tables:
    table.clean_up()

Wenn ich laufe main.py, läuft alles bis zur letzten Schleife, dh for table in tables: table.clean_up(). Es bleibt einfach dort hängen, keine Fehler oder Warnungen.

Wenn diese Methode selbst ausgeführt wird, funktioniert sie einwandfrei, dh sie schneidet die Postgres-Tabellen ab. Benötigen Sie Hilfe, damit dies funktioniert, und verstehen Sie, warum die endgültige Methode nicht ausgeführt wird, wenn alle anderen ausgeführt werden.

Ausgabe von, wenn clean_up()alleine ausgeführt:

Truncating bookings...DONE
Removing bookings.csv...DONE

Truncating bookings2...DONE
Removing bookings2.csv...DONE

Truncating channel...DONE
Removing channel.csv...DONE

Truncating cost...DONE
Removing cost.csv...DONE

Was der Gesamtcode bewirkt:

  1. Abrufen von Dateien mit SQL-Abfragen, die Daten aus verschiedenen Datenbanken extrahieren und diese Abfragen ausführen.
  2. Exportieren nach CSV
  3. Importieren von CSVs in eine Postgres-Datenbank
  4. Schreiben einer Postgres-Abfrage, die Daten zusammenführt und dann als CSV exportiert, um sie in einem BI-Tool zur Datenvisualisierung zu verwenden
  5. Abschneiden der Daten in Postgres und Löschen der CSV-Dateien in Punkt 2

Sie denken wahrscheinlich, dass dies ein Wahnsinn ist und ich stimme zu. Ich mache derzeit mit dem, was ich habe, fällig und kann keine Daten auf meinem Computer speichern, weil es sich um Unternehmensdaten handelt (daher das Abschneiden und Entfernen der Daten).

AK91
quelle
2
Ich kann in dem, was Sie über Ihren Python-Code gepostet haben, nichts sehen, was dieses Problem verursacht. Daher liegt das Problem höchstwahrscheinlich bei Postgres.
Bruno Desthuilliers
Können Sie die Ausgabe Ihrer clean_up () -Methode veröffentlichen, wenn Sie eine eigene ausführen?
Kederrac

Antworten:

5

TRUNCATEDie Klausel in Postgres erfordert eine ACCESS EXCLUSIVESperre der Beziehung und kann auch einige BEFORE TRUNCATEAuslöser auslösen.

Ich vermute, dass das Problem auf der Postgres-Seite liegt, z. B. TRUNCATEversucht, ACCESS EXCLUSIVEdie Beziehung zu sperren, aber es wird bereits von jemand anderem gesperrt.

Überprüfen Sie zunächst Ihre Postgres-Protokolle.

Überprüfen Sie als Nächstes, was Ihre Postgres-Backends während Ihres Hangings tun TRUNCATEmit:

SELECT * FROM pg_stat_activity;

Untersuchen Sie als Nächstes die Sperren mit:

-- View with readable locks info and filtered out locks on system tables
CREATE VIEW active_locks AS
SELECT clock_timestamp(), pg_class.relname, pg_locks.locktype, pg_locks.database,
       pg_locks.relation, pg_locks.page, pg_locks.tuple, pg_locks.virtualtransaction,
       pg_locks.pid, pg_locks.mode, pg_locks.granted
FROM pg_locks JOIN pg_class ON pg_locks.relation = pg_class.oid
WHERE relname !~ '^pg_' and relname <> 'active_locks';

-- Now when we want to see locks just type
SELECT * FROM active_locks;
Ololobus
quelle
Danke dafür. Ich habe die Ansicht wie gezeigt erstellt, die Ausgabe ist leer
AK91
OK, was ist mit pg_stat_activity? Was machen andere Backends? ZB mitSELECT * FROM pg_stat_activity WHERE backend_type = 'client backend' AND datname IS NOT NULL;
Ololobus
2

Ich würde Ihnen vorschlagen, den gewünschten Bereinigungsprozess in einer Transaktion durchzuführen. Um unerwünschte Zustände zu verhindern.

Überprüfen Sie mithilfe des Informationsschemas, ob eine Tabelle in der Datenbank vorhanden ist

SELECT EXISTS (
   SELECT 1
   FROM   information_schema.tables 
   WHERE  table_schema = 'schema_name'
   AND    table_name = 'table_name'
   );

Überprüfen Sie, ob vorhanden, erstellen Sie Ihre Kürzungsbefehle.

und führen Sie den Bereinigungsprozess in einer Transaktion aus.

Frederic
quelle