首页 > 编程学习 > python进程池(子进程)函数没有执行

python进程池(子进程)函数没有执行

发布时间:2022/5/14 15:53:47

文章目录

    • 1. 问题描述
    • 问题排查经过
    • 关于此问题的两个可能原因

内容较长

1. 问题描述

某日,写了一段爬虫代码(如下,爬取糗百图片代码示例),发现一个异常的问题,就是执行代码时,代码会以极快的速度执行完成,但是任何东西都没有爬取下来,经过问题排查,确认为下载方法downloadEngin内没有执行,我特意在for循环向线程池提交任务处添加了print,执行代码后会print所有提交信息,但是方法downloadEngin里面的print一条没有输出.

from multiprocessing import Pool
from requests import Session
from lxml import etree

class getData:
    def __init__(self):
        self.session = Session()
        self.headers = {
            'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3766.400 QQBrowser/10.6.4163.400'
        }
    def downloadEngin(self,downloadUrl,fileName):
        print("开始下载",downloadUrl,fileName)
        pictureData = self.session.get("http:" + downloadUrl,headers = self.headers).content
        with open(fileName + '.jpg',mode="wb") as w:
            w.write(pictureData)
    def getPage(self,url):
        pageData = self.session.get(url,headers = self.headers).content.decode('utf-8')
        self.xpath = etree.HTML(pageData)
        pictureName = self.xpath.xpath('/html/body/div[1]/div/div[2]/div/div[2]/a/img/@src')
        pool = Pool(10)
        for i in range(len(pictureName)):
            print("提交任务:{}".format(i))
            pool.apply_async(self.downloadEngin,args=(pictureName[i],str(i)))
        pool.close()
        pool.join()
if __name__ == '__main__':
    getData().getPage('https://www.qiushibaike.com/imgrank/')

上段代码执行效果:

提交任务:0
提交任务:1
提交任务:2
提交任务:3
提交任务:4
.....
提交任务:22
提交任务:23
提交任务:24

进程已结束,退出代码为 0

问题排查经过

我反复确认了代码写的没有问题,仔细想了一下可能影响到多线程任务执行的问题,想到了变量.
提交任务时传递了两个参数,如下,此处先是统计了列表长度然后生成对应的数字,然后开始提交任务

pool.apply_async(self.downloadEngin,args=(pictureName[i],str(i)))

传递参数为:列表的实际内容和列表所在的下标索引的数字值,并将数字转换为字符串,作为保存的文件名.

我在for循环上面添加输出了这个列表,列表内容没有问题,随后,我将整段列表复制下来,在for循环的上面位置,重新定义了这个变量的内容

# ['xxx','yyy'] 为之前复制的整段列表内容
pictureName = ['xxx','yyy']

然后重新执行代码,惊疑的发现可以运行了.

此处的问题很明显了,我就使用最笨的方法不断的将上面和这个变量相关的代码注释,手动赋值等操作,终于定位到了有问题的两行代码.
上面只是示例,当时文件内容多很多,xpath声明为全局是因为还有其他方法要用它

self.xpath = etree.HTML(pageData)
pictureName = self.xpath.xpath('/html/body/div[1]/div/div[2]/div/div[2]/a/img/@src')

上面是有问题代码,解决方式是删除self,下面是修改后的代码

xpath = etree.HTML(pageData)
pictureName = xpath.xpath('/html/body/div[1]/div/div[2]/div/div[2]/a/img/@src')

然后重新执行,可以了.

关于此问题的两个可能原因

  1. 如果也是在for循环提交任务中添加了print,并且可以正常输出,那么多半是传递的变量有问题,可以在源代码基础上先在for循环上面固定变量的值重新运行尝试
  2. 还有一种情况是多进程函数执行了,也就是上面的downloadEngin中的第一行print代码可以正常输出,但是依旧没有将爬取的数据保存下来,也就是除去了第一行代码其他还是类似没有执行,这种情况一般为多进程执行的函数中的代码写的有问题,某种情况下,Python创建的子进程执行错误不会将错误抛出,而是直接结束了子进程,在控制台看不到任何错误输出,只能将子进程函数复制出来一点点执行排查了.
Copyright © 2010-2022 ngui.cc 版权所有 |关于我们| 联系方式| 豫B2-20100000