今天在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()
这样,便可以解决上文中所述的问题了。