実行/実行に永遠にかかる単純なPythonメソッド


8

私のコードがclean_up()メソッドでスタックしますMyClass()

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()

私が実行するmain.pyと、最後のループまですべてが実行されますfor table in tables: table.clean_up()。エラーや警告は発生せず、そこでスタックするだけです。

そのメソッドを独自に実行すると、正常に機能します。つまり、postgresテーブルが切り捨てられます。これを機能させ、他のすべてのメソッドが実行されたときに最終メソッドが実行されない理由を理解するのに助けが必要です。

clean_up()単独で実行した場合の出力:

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

コード全体の機能:

  1. さまざまなデータベースからデータを抽出してそれらのクエリを実行するSQLクエリを含むファイルを取得します。
  2. それらをcsvにエクスポートする
  3. csvをpostgresデータベースにインポートする
  4. データをまとめて、データを視覚化するためのBIツールで使用するcsvとしてエクスポートするpostgresクエリを作成する
  5. postgresのデータを切り捨て、ポイント2でcsvファイルを削除する

あなたはおそらくこれが狂気だと思っているでしょうし、私も同意します。私は現在、私が持っているもので支払いを行っていますが、会社のデータ(したがって、データの切り捨てと削除)のため、自分のコンピューターにデータを保存できません。


2
あなたがあなたのPythonコードに投稿したものにこの問題を引き起こしているものは何も見当たらないので、この問題は恐らくpostgresにあります。
bruno desthuilliers

独自に実行するときに、clean_up()メソッドの出力をポストできますか?
ケデラック

回答:


5

TRUNCATEPostgresの句ACCESS EXCLUSIVEはリレーションをロックする必要があり、いくつかのBEFORE TRUNCATEトリガーを起動することもできます。

私の推測では、問題はPostgres側にあります。たとえば、関係のロックTRUNCATEを取得しようとしACCESS EXCLUSIVEますが、すでに他の誰かによってロックされています。

まず、Postgresログを確認します。

次に、ハングしたときにPostgresバックエンドが何をしているかを確認しますTRUNCATE

SELECT * FROM pg_stat_activity;

次に、次の方法でロックを調査します。

-- 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;

これをありがとう。表示した
とおりに

OK、pg_stat_activityとは何ですか?他のバックエンドは何をしていますか?と例えばSELECT * FROM pg_stat_activity WHERE backend_type = 'client backend' AND datname IS NOT NULL;
ololobus

2

1つのトランザクションですべての目的のクリーンプロセスを実行することをお勧めします。望ましくない状態を防ぐため。

そして、information_schemaを使用して、テーブルがデータベースに存在するかどうかを確認します。

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

存在する場合は、切り捨てコマンドを作成します。

クリーンプロセスをすべて1つのトランザクションで実行します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.