首页 > 编程问答 >多重处理会导致 Python 崩溃,并给出一个错误:调用 fork() 时可能已在另一个线程中进行

多重处理会导致 Python 崩溃,并给出一个错误:调用 fork() 时可能已在另一个线程中进行

时间:2024-07-24 10:39:59浏览次数:12  
标签:python python-3.x multithreading macos

我对 Python 比较陌生,并试图为我的 for 循环实现一个多处理模块。

我在 img_urls 中存储了一个图像 url 数组,我需要下载并应用一些 Google 视觉。

if __name__ == '__main__':

    img_urls = [ALL_MY_Image_URLS]
    runAll(img_urls)
    print("--- %s seconds ---" % (time.time() - start_time)) 

这是我的 runAll( ) 方法

def runAll(img_urls):
    num_cores = multiprocessing.cpu_count()

    print("Image URLS  {}",len(img_urls))
    if len(img_urls) > 2:
        numberOfImages = 0
    else:
        numberOfImages = 1

    start_timeProcess = time.time()

    pool = multiprocessing.Pool()
    pool.map(annotate,img_urls)
    end_timeProcess = time.time()
    print('\n Time to complete ', end_timeProcess-start_timeProcess)

    print(full_matching_pages)


def annotate(img_path):
    file =  requests.get(img_path).content
    print("file is",file)
    """Returns web annotations given the path to an image."""
    print('Process Working under ',os.getpid())
    image = types.Image(content=file)
    web_detection = vision_client.web_detection(image=image).web_detection
    report(web_detection)

当我运行它并且 python 崩溃时,我收到此警告

objc[67570]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called.
objc[67570]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.
objc[67567]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called.
objc[67567]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.
objc[67568]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called.
objc[67568]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.
objc[67569]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called.
objc[67569]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.
objc[67571]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called.
objc[67571]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.
objc[67572]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called.
objc[67572]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.

此错误消息表明正在使用 macOS 上的 multiprocessing 库遇到问题,而问题源于 fork() 与某些库(如请求库)交互的方式。 让我们分解一下原因以及如何解决该问题。

问题根源

  • fork(): multiprocessing 库(默认情况下在 macOS 上)使用一种称为 fork() 的机制来创建新进程。 fork() 本质上是创建一个与父进程相同状态的子进程。
  • 线程和库不兼容性: 某些库(包括可能正在使用的用于网络的 requests )或 macOS 上的 GUI 框架,在分叉的进程中与线程和内部状态的处理方式不兼容。当一个进程使用 fork() 创建时,它会继承所有线程,但并非所有线程状态都以线程安全的方式复制,从而导致崩溃或意外行为。

解决方案

  1. 使用“spawn”或“forkserver”启动方法:

  2. spawn: 此方法为每个进程启动一个全新的解释器,从而避免继承不兼容的线程状态。这是 macOS 上推荐的方法。

  3. forkserver: 此方法创建一个服务器进程来派生新的 Python 进程。它比“spawn”快,但设置起来更复杂。

可以使用 set_start_method 在代码中更改启动方法:

```python import multiprocessing

if name == ' main ': multiprocessing.set_start_method("spawn") # 或 "forkserver" # ... 的代码的其余部分 ... ```

  1. 将有问题的代码移至主进程之后:

  2. 如果可能,请重构代码,以便调用 requests 或其他可能导致问题的库的代码 子进程中执行,而不是在分叉发生之前执行。这确保了有问题的初始化发生在子进程上下文中。

示例(使用“spawn”):

import multiprocessing
import time
import requests
from google.cloud import vision
from google.cloud.vision import types

# 初始化 Google Vision 客户端
vision_client = vision.ImageAnnotatorClient()

def annotate(img_path):
    """返回给定图像路径的网络注释。"""
    print('进程在以下进程下工作:', os.getpid())
    file = requests.get(img_path).content  # 在子进程中执行请求
    image = types.Image(content=file)
    web_detection = vision_client.web_detection(image=image).web_detection
    # 处理 web_detection...

def runAll(img_urls):
    # ...(代码的其余部分)

if __name__ == '__main__':
    multiprocessing.set_start_method("spawn")
    img_urls = [ALL_MY_Image_URLS]
    runAll(img_urls)
    print("--- %s seconds ---" % (time.time() - start_time))

其他提示:

  • 库文档: 如果使用的是除 requests 之外的其他库,请查阅其文档以了解它们是否对分叉进程有任何特定说明或限制。
  • 调试: 如果问题仍然存在,请尝试使用调试器来查明导致崩溃的确切代码行。这可以帮助查明是否有任何意外交互。

通过切换到“spawn”启动方法或重构代码以避免在分叉之前进行有问题的初始化,应该能够解决此多处理问题。

标签:python,python-3.x,multithreading,macos
From: 50168647

相关文章

  • Python编程时输入操作数错误
    我正在用Python编写下面的代码来模拟控制系统。但是,当我调试代码时,我面临以下问题:matmul:输入操作数1没有足够的维度(有0,gufunc核心,签名为(n?,k),(k,m?)->(n?,m?)需要1)文件“D:\ÁreadeTrabalho\GitHub\TCC\CódigosMarcela\SistemaSISO_tres_estados_new.py”,......
  • Python入门知识点 7--散列类型与字符编码
    1、初识散列类型(无序序列)数据类型分为3种:   前面已经学过了两种类型   1.数值类型:int/float/bool只能存储单个数据      2.序列类型:str/list/tuple,有序的存储多个数据--有序类型,有下标,可以进行索引切片步长操作          3.散列类型......
  • Python入门知识点 6--序列类型的方法
    1、初识序列类型方法序列类型的概念:数据的集合,在序列类型里面可以存放任意的数据也可以对数据进行更方便的操作这个操作就是叫增删改查(crud)(增加(Creat),读取查询(Retrieve),更新(Update),删除(Delete)几个单词的首字母简写)增删改查是操作数据最底层的操作(从本质......
  • Python项目流程图
    我有一个由多个文件夹组成的Python项目,每个文件夹包含多个脚本。我正在寻找一个Python库或软件/包,它们可以生成流程图,说明这些脚本如何互连并绘制出从开始到结束的整个过程。自动生成Python项目流程图确实是一个挑战,目前没有完美通用的解决方案。主要原因是:......
  • 使用 mypy 时Python中的继承和多态性不起作用
    我正在寻找用mypy做一些标准的多态性,我以前从未使用过它,而且到目前为止它并不直观。基类classContentPullOptions:passclassTool(Protocol):asyncdefpull_content(self,opts:ContentPullOptions)->str|Dict[str,Any]:...子类classGoogle......
  • Python函数获取匹配和错误记录
    我有一个以下格式的json文件:[{"type":"BEGIN","id":"XYZ123"},{"type":"END","id":"XYZ123",},{"type":&......
  • python,替换标点符号但保持特殊单词完整的最佳方法
    我正在制作一个调制函数,它将采用带有特殊字符(@&*%)的关键字,并保持它们完整,同时从句子中删除所有其他标点符号。我设计了一个解决方案,但它非常庞大,而且可能比需要的更复杂。有没有一种方法可以以更简单的方式做到这一点。简而言之,我的代码匹配特殊单词的所有实例以查找跨度。然......
  • Python 检测 USB 设备 - IDLE 和 CMD 解释器之间的不同结果
    我正在尝试解决VDI解决方案中智能卡设备的USB重定向问题。我正在使用pyscard模块作为智能卡。对于进一步的上下文,主要问题是当浏览器插件调用用于处理智能卡的python脚本时,未检测到读卡器。关于问题,当我从CMD解释器运行此代码片段时,我收到空列表,表示系统上未找......
  • Python查找字符串的CRC32
    我尝试获取字符串数据类型变量的CRC32,但出现以下错误:>>>message='helloworld!'>>>importbinascii>>>binascii.crc32(message)Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>TypeError:aby......
  • 使用python,如何创建重复的工作时间表
    这是我们公司的小组工作安排表。为三班制,2组日夜工作,1组休息。重复白天工作4天休息2天,然后再次夜间工作4天休息2天的时间表。我想使用python(pandas)自动安排在8月9日之后。抱歉英语不好,提前感谢您的帮助以下是使用Python和Pandas创建重复工作时间表的代码......