pymongo中的MongoClient opened before fork警告原因及解决方法

今天在python中遇到了一个警告,如下:

UserWarning: MongoClient opened before fork. Create MongoClient only after forking. See PyMongo's documentation for details: http://api.mongodb.org/python/current/faq.html#is-pymongo-fork-safe
  "MongoClient opened before fork. Create MongoClient only "

查找资料后发现,是在多进程环境中,一个MongoClient实例不应该被当作参数在不同进程间进行传递。PyMongo是线程安全的,但并不是进程安全的,以本文中的demo为例,MongoClient的实例不应该从父进程传递到子进程,这两个进程应该各自创建属于自己的MongoClient实例,否则,可能会发生死锁等意外情况,而上面的警告便是提醒这些操作。

def insert_data(target_db, data_list):
    target_db.insert_many(data_list)


if __name__ == '__main__':
    # 这里将测试的数据库的地址替换为了*
    source_db = MongoClient('mongodb://admin:admin@*.*.*.*:*')['test_db']['test_1_13_1']
    target_db = MongoClient('mongodb://admin:admin@*.*.*.*:*')['test_db']['test_1_13_2']

    cursor = source_db.find().limit(100)
    print(cursor.count(True))

    doc_list = []

    for doc in cursor:
        doc_list.append(doc)

    # 这里将父进程中创建的MongoClient实例传递到了子进程中,导致了上文所述的警告
    p = Process(target=insert_data, args=(target_db, doc_list))
    p.start()

此时,可以将代码改为:

def insert_data_with_new_client(db_url, db_name, col_name, data_list):
    # 这里在子进程中创建了一个新的MongoClient的实例
    target_client = MongoClient(db_url)
    target_col = target_client[db_name][col_name]
    target_col.insert_many(data_list)
    # 尽量及时关闭连接,否则子进程较多的时候可能会发生连接较多的情况
    target_client.close()



if __name__ == '__main__':
    # 这里将测试的数据库的地址替换为了*
    source_db = MongoClient('mongodb://admin:admin@*.*.*.*:*')['test_db']['test_1_13_1']
    target_db = MongoClient('mongodb://admin:admin@*.*.*.*:*')['test_db']['test_1_13_2']

    cursor = source_db.find().limit(100)
    print(cursor.count(True))

    doc_list = []

    for doc in cursor:
        doc_list.append(doc)

    url = 'mongodb://panruijie:[email protected]:30011'
    db_name = 'tweet_stream'
    col_name = 'test_1_14_0'
    p = Process(target=insert_data_with_new_client, args=(url, db_name, col_name, doc_list))
    p.start()

这样,便可以解决上文中所述的问题了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章