首页 > 解决方案 > 分配可挑选的全局变量

问题描述

如果这是一个容易解决的问题,我很抱歉,我已经尝试过搜索但无法找到解决方案。我来自 PHP,所以也许我想要实现的目标是不可能的,或者它需要在 python 中以不同的方式完成。

好的,所以我有一个名为的类database.py,它解析配置文件,并根据我使用的“数据库”类型返回一个对象sqlitemysql

数据库.py

import mysql.connector
from mysql.connector import Error
from mysql.connector import pooling


class Database:

    # Connect to the database
    @staticmethod
    def connect():
        if Config().type() == 'mysql':
            return mysql.connector.pooling.MySQLConnectionPool(**Config().mysql())
        elif Config().type() == 'sqlite':
            return sqlite3.connect("%s.sqlite" % Config().sqlite())

所以,正如你所看到的,我正在返回我正在使用的数据库的一个对象,对于这个例子,假设Config().type() == 'mysql'是真的,我们正在使用mysql,而 theConfig().mysql()只是一个像这样的字典:

{
    'pool_name': "indexit",
    'pool_size': config['DATABASE']['mysql']['pool_size'],
    'pool_reset_session': True,
    'user': config['DATABASE']['mysql']['user'],
    'password': config['DATABASE']['mysql']['password'],
    'host': config['DATABASE']['mysql']['host'],
    'database': config['DATABASE']['mysql']['database'],
    'auth_plugin': 'mysql_native_password',
    'charset': 'utf8',
    'use_unicode': True
}

在我的主要 python 文件中,我试图将 分配Database.connect()给一个变量,然后在我的线程函数中使用它并从对象中获取 mysql 池:

from multiprocessing import Pool
from core.database import Database

class Indexit:

    # MyProgram constructor
    def __init__(self):
        # 1 connection for threads
        self.database = Database.connect()

    # Thread to run
    def run(self, id):
        # return the id
        print(id)

        # Get the database pool
        print(self.database.get_connection())

    # Do the threads
    def main(self):
        # Pool connections
        with Pool(processes=5) as pool:
            pool.map(self.run, range(10000000))

Indexit().main()

但我的代码返回错误:(您可以在此处查看完整代码:https ://github.com/filter/indexit )

Traceback (most recent call last):
  File "indexit.py", line 75, in <module>
    Indexit().main()
  File "indexit.py", line 68, in main
    pool.map(self.run, range(10000000))
  File "/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/multiprocessing/pool.py", line 268, in map
    return self._map_async(func, iterable, mapstar, chunksize).get()
  File "/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/multiprocessing/pool.py", line 657, in get
    raise self._value
  File "/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/multiprocessing/pool.py", line 431, in _handle_tasks
    put(task)
  File "/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/multiprocessing/connection.py", line 206, in send
    self._send_bytes(_ForkingPickler.dumps(obj))
  File "/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/multiprocessing/reduction.py", line 51, in dumps
    cls(buf, protocol).dump(obj)
TypeError: can't pickle _thread.lock objects

所以,我的问题是,我怎样才能使用全局连接,然后使用我的线程函数来获得自己的池工作者?

标签: pythonpython-3.x

解决方案


显然,在MySQLConnectionPool内部使用线程。当您调用mapa 的方法时multiprocessing.Pool,它会尝试发送运行给定函数所需的所有内容。在这种情况下包括数据库连接池。

当一个新进程被创建时,它只有一个线程。因此,尝试将与线程相关的东西(如锁)发送给子进程是没有意义的。锁拥有的任何数据在子进程中都将毫无意义。因此错误。

您可能应该池工作者或Pool.


推荐阅读