解决jupyter使用多线程multiprocessing怕不了的报错问题,并使用tqdm显示进度条

最近在工作上需要进行一个爬虫的演示,需要在界面上输入账号,密码,然后开始爬取数据,需要使用多进程爬虫以加快爬取速度,之前一直没用过多进程,Pycharm可以跑,但需要在jupyter上运行(Pycharm使用不了getpass隐藏输入),所以今天写代码时候遇到了不少问题,在此总结一下。

python版本3.7.6
jupyter lab版本1.2.6

①jupyter notebook/lab中直接使用多进程的话,虽然在界面上不会报错,但一直会处于运行状态,去查看命令行的话会看到报错:
AttributeError: Can’t get attribute ‘XXX’ on <module ‘main’ >,由于某些原因Pool不能始终使用未在导入的模块中定义的对象。
②运行时报错:
AttributeError: module ‘main’ has no attribute ‘spec’,这时需要在if name == ‘main’:下面加上:
spec = “ModuleSpec(name=‘builtins’, loader=<class ‘_frozen_importlib.BuiltinImporter’>)”

jupyter只能跟踪主进程,没法跟踪子进程,网上有一些其他的解决办法,但个人觉得最简单的还是将代码打包成py文件,再让jupyter执行这个文件,代码如下:

因为爬虫需要输入账号,密码获取cookie,所以这里为了测试写了个函数输入账号,然后传入worker和main函数中,看是否能正常运行

%%writefile  test.py
import os,time
from multiprocessing import Pool
from tqdm import tqdm
import getpass
import time
def user_info():
    user = input('请输入用户名:')
    psw = getpass.getpass('请输入密码:')#隐藏密码
    return user,psw
    
def worker(x,user,psw):
    return x*x
    
def main(user,psw):
    lst = []
    print("主进程开始执行>>> pid={}".format(os.getpid()))
    ps=Pool(processes=12)
    with tqdm(total=len(range(500))) as t:
        for i in range(500):
            res = ps.apply_async(worker,args=(i,user,psw)) # 异步执行,args为传入的参数
            print(i)
            t.update()
            time.sleep(0.1)
        # 关闭进程池,停止接受其它
        ps.close()
        # 阻塞进程
        ps.join()
        print("主进程终止")
if __name__ == '__main__':
    user,psw = user_info()
    print(user)
    __spec__ = "ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>)"#
    main(user,psw)

执行上面代码会在默认路径下生成一个.py文件
在这里插入图片描述
然后再run一:下

%run test.py

在这里插入图片描述
大功告成!

猜你喜欢

转载自blog.csdn.net/weixin_43785299/article/details/109301646