Ошибка подключения к PostgreSQL не может выбрать объекты psycopg2.extensions.connection - PullRequest
0 голосов
/ 30 марта 2020

Я пытаюсь создать архитектуру, которая будет иметь основной родительский процесс и может создавать новые дочерние процессы. Главный родительский процесс всегда будет на l oop, чтобы проверить, доступен ли какой-либо дочерний процесс.

Я использовал ThreadedConnectionPool модуля psycopg2.pool для создания общего подключения к базе данных для всех созданных дочерних процессов. , Это означает, что программа будет один раз подключаться к базе данных и выполнять все запросы SQL для каждого из дочерних процессов. Таким образом, нет необходимости каждый раз подключаться к базе данных для выполнения SQL запросов.

Код выглядит следующим образом:

from multiprocessing import Process, Lock
import time, os, psycopg2
from psycopg2 import pool

def child(dbConnection, lock, num, pid, sleepTime, query):
    lock.acquire()

    start = time.time()

    print("Child Process {} - Process ID: {}".format(num + 1, str(os.getpid())))

    db_cursor = dbConnection.cursor()
    db_cursor.execute(query)
    records = db_cursor.fetchmany(2)

    print("Displaying rows from User Master Table")

    for row in records:
        print(row)

    print("Executed Query:", query)
    print("Child Process {} - Process ID {} Completed.".format(num + 1, str(os.getpid())))

    end = time.time()
    print("Time taken:", str(end - start), "seconds")

    lock.release()
    time.sleep(sleepTime)

if __name__ == "__main__":
    try:
        connectionPool = psycopg2.pool.ThreadedConnectionPool(5, 21, user = "dwhpkg", password = "dwhpkg", host = "127.0.0.1", port = "5432", database = "dwhdb")

        while True:

            processes = []

            print("Main Process ID: {}".format(str(os.getpid())))
            lock = Lock()


            # 21 Times Process Execution
            for count in range(21):
                if connectionPool :
                    print("Connection Pool Successfully Created")

                # Getting DB Connection From Connection Pool
                dbConnection = connectionPool.getconn()

                if dbConnection:
                    sql_execute_process = Process(target = child, args = (dbConnection, lock, count, os.getpid(), 4, 'SELECT * FROM public."USER_MASTER"',))

                    sql_execute_process.start()

                    processes.append(sql_execute_process)
                    print("Parent Process:", os.getpid())

                    print(processes)

                    time.sleep(5)

            for process in processes:
                process.join()

    except (Exception, psycopg2.DatabaseError) as error:
        print("Error Connecting To PostgreSQL", error)

    finally:
        # Closing DB Connection
        if connectionPool:
            connectionPool.closeall
        print("Connection Pool is closed")

При попытке запустить приведенный выше код выдает следующую ошибку:

Main Process ID: 46700
Connection Pool Successfully Created
Error Connecting To PostgreSQL can't pickle psycopg2.extensions.connection objects
Connection Pool is closed

(task_env) C:\Users\sicuser\Desktop\ジート\03_作業案件\タスク機能プロトタイプ作成\開発>Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\Users\sicuser\AppData\Local\Programs\Python\Python37\lib\multiprocessing\spawn.py", line 99, in spawn_main
    new_handle = reduction.steal_handle(parent_pid, pipe_handle)
  File "C:\Users\sicuser\AppData\Local\Programs\Python\Python37\lib\multiprocessing\reduction.py", line 82, in steal_handle
    _winapi.PROCESS_DUP_HANDLE, False, source_pid)
OSError: [WinError 87] The parameters are incorrect.

Для устранения неполадок также использовал режим отладки и попытался выяснить местоположение ошибки. Используя отладку, я обнаружил, что ошибка происходит из-за следующей строки:

sql_execute_process.start()

Message Сообщение об ошибке】

Main Process ID: 47708
Connection Pool Successfully Created
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\Users\sicuser\AppData\Local\Programs\Python\Python37\lib\multiprocessing\spawn.py", line 105, in spawn_main
    exitcode = _main(fd)
  File "C:\Users\sicuser\AppData\Local\Programs\Python\Python37\lib\multiprocessing\spawn.py", line 115, in _main
    self = reduction.pickle.load(from_parent)
EOFError: Ran out of input
Error Connecting To PostgreSQL can't pickle psycopg2.extensions.connection objects

Среда ОС Windows и Python версия: Python 3.7.4

Ждем поддержки от экспертов.

1 Ответ

0 голосов
/ 30 марта 2020

В приведенном выше решении вы используете ThreadedConnectionPool с multiprocessing.Process экземплярами ( thread! = Process ).
Несколько процессов не могут безопасно использовать одно и то же соединение; проверьте подробности в разделе psycopg о потоке и безопасности процесса .

Вы также используете Lock для критического кода в дочернем элементе, который в основном мешает вам выполнять задачи параллельно; даже если бы это работало, производительность в значительной степени была бы такой же, как для решения с одним процессом.

Решение зависит от того, насколько интенсивным и продолжительным будет процессинг дочерних процессов:

  • , если дети будут легкими / недолговечными, просто сделайте всю работу, используя один (основной) поток
  • для тяжелых / долгоживущих дочерних процессов, подключающихся к базе данных изнутри дочернего процесса (не разделяйте соединение с основной процесс)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...