Python多处理池在地图调用中挂起

时间:2015-10-07 15:07:27

标签: python mysql multiprocessing

我有一个解析文件的函数,并使用SQLAlchemy将数据插入MySQL。我一直在os.listdir()的结果上按顺序运行该函数,一切都运行良好。

因为大部分时间都花在阅读文件和写入数据库上,所以我想使用多处理来加快速度。这是我的pseduocode,因为实际代码太长了:

def parse_file(filename):
    f = open(filename, 'rb')
    data = f.read()
    f.close()

    soup = BeautifulSoup(data,features="lxml", from_encoding='utf-8')

    # parse file here

    db_record = MyDBRecord(parsed_data)

    session.add(db_record)
    session.commit()

pool = mp.Pool(processes=8)

pool.map(parse_file, ['my_dir/' + filename for filename in os.listdir("my_dir")])

我看到的问题是脚本挂起并且永远不会完成。我通常会将63条记录中的48条记录到数据库中。有时它更多,有时它更少。

我已尝试使用pool.close()并与pool.join()结合使用,似乎没有任何帮助。

如何完成此脚本?我究竟做错了什么?我在Linux机器上使用Python 2.7.8。

2 个答案:

答案 0 :(得分:3)

您需要将所有使用多处理的代码放在其自己的函数中。当多处理在单独的进程中重新导入模块时,这会阻止它以递归方式启动新池:

def parse_file(filename):
    ...

def main():
    pool = mp.Pool(processes=8)
    pool.map(parse_file, ['my_dir/' + filename for filename in os.listdir("my_dir")])

if __name__ == '__main__:
    main()

请参阅有关making sure your module is importable的文档,以及advice for running on Windows(tm)

答案 1 :(得分:2)

问题是两件事的结合:

  1. 我的泳池代码被多次调用(感谢@Peter Wood)
  2. 我的数据库代码打开了太多会话(和/或)共享会话
  3. 我做了以下更改,现在一切正常: 原始文件

    def parse_file(filename):
        f = open(filename, 'rb')
        data = f.read()
        f.close()
    
        soup = BeautifulSoup(data,features="lxml", from_encoding='utf-8')
    
        # parse file here
    
        db_record = MyDBRecord(parsed_data)
    
        session = get_session() # see below
        session.add(db_record)
        session.commit()
    
    pool = mp.Pool(processes=8)
    
    pool.map(parse_file, ['my_dir/' + filename for filename in os.listdir("my_dir")])
    

    数据库文件

    def get_session():
        engine = create_engine('mysql://root:root@localhost/my_db')
    
        Base.metadata.create_all(engine)
        Base.metadata.bind = engine
    
        db_session = sessionmaker(bind=engine)
    
        return db_session()