【问题标题】:Simple Python method taking forever to execute/run简单的 Python 方法需要永远执行/运行
【发布时间】:2020-04-16 03:00:28
【问题描述】:

我的代码卡在MyClass() 中的clean_up() 方法

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

ma​​in.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. 编写一个 postgres 查询,将数据汇集在一起​​,然后导出为 csv 以在 BI 工具中用于数据可视化
  5. 截断 postgres 中的数据并删除第 2 点中的 csv 文件

您可能认为这是一种疯狂,我同意。我目前正在使用我所拥有的东西,并且无法在我的计算机上存储数据,因为它是公司数据(因此会截断和删除数据)。

【问题讨论】:

  • 我在您发布的 Python 代码中看不到任何导致此问题的原因,因此问题很可能确实出在 postgres 上。
  • 您可以在运行自己的 clean_up() 方法时发布其输出吗?

标签: python sql python-3.x postgresql


【解决方案1】:

Postgres 中的TRUNCATE 子句需要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;

【讨论】:

  • 谢谢。如您所示,我创建了视图,输出为空
  • 好的,pg_stat_activity 是什么?其他后端在做什么?例如。 SELECT * FROM pg_stat_activity WHERE backend_type = 'client backend' AND datname IS NOT NULL;
【解决方案2】:

我建议您在一笔交易中完成所需的清洁过程。防止出现不希望的状态。

并使用 information_schema 检查表是否存在于数据库中

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

检查如果存在,创建你的截断命令。

并在一个事务中执行清理过程。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-23
    • 1970-01-01
    • 1970-01-01
    • 2020-04-03
    • 1970-01-01
    相关资源
    最近更新 更多