Python多进程传参总出错?Process参数全讲透
2026/9/13 23:54:43 网站建设 项目流程

凭借多进程去运行任务, 参数怎么都没法传进去, 控制台给你抛出一行内容: ‘int’ 并非——要是你编写过下面这行程序代码, 大概见过这个错误提示:

p = Process(target=speak, args=(666))

问题就出在一个逗号上。

对于这事儿, 真的并非是你的过错。有这样一个类, 该类的参数总共存在6个, 然而众多教程一开始仅仅教你去写=函数名, 其余的5个则是被一言带过。等到你自己实实在在需要运用它们的时候所面临的情况是, 究竟哪个参数放置在何处, 以及该如何进行传递, 这一切都只能依靠猜测。

今儿就将那参数逐个儿掰开来讲明白。瞅完这一篇, 你不但能够把参数传对, 而且还能够晓得你那子进程究竟叫啥名儿。

一、先看全貌: 到底能接几个参数

我们先把完整签名摆出来:

Process(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)

一共 6 个:group、、name、args、、。

为了方便理解,你可以把创建进程想象成公司招一个员工去干活:

下面挨个说。

二、group:最没存在感的参数,别管它

留心瞧, group属于首个参数, 然而, 是第二个。故而要是依照位置传递参数, 头一个位置实际上是为group预留的——这便是为何平常我们都规规矩矩写=xxx这种关键字形式。

默认值属于group的是None, 官方文档表述得更为直接明白: 始终应为None的是group。

那它所具有的存在意义究竟是什么呢? 官方给出的相应解释是这样的: 它的存在单单只是为了与.存在保持一种兼容的状态。简单明了地讲 , 就是为了在你从多线程切换到多进程的这个时候 , 代码呈现出来的样子大致比较相像 , 不需要重新去学习一整套有着不同特点的写法。

没啥好对这个参数纠结的, 人家是怎样说的, 那咱们就怎样去做, 永远不要传, 如同当作它不存在一样。

三、:核心参数,指定子进程要干的活儿

最多被我们平时所使用, 它接纳一个函数对象(要注意是函数名称, 别去添加括号)

def speak(): print("子进程在说话") if __name__ == "__main__": p = Process(target=speak) # 对,写 speak p2 = Process(target=speak()) # 错!这样是先把函数执行了 p.start() p.join()

为用户着重提示: 用于创建进程的一连串代码, 务必得放置于 if =="" 这个特定条件的范围之内。不然的话, 后续流程便会无休止地以递归形式去创建子进程, 那种情况会直接致使内存被彻底耗尽。这并非是什么玄虚神秘论说, 而是由于与 Linux 创建进程的底层机制存在差异所引发导致出现这样子的结果的。

四、name:给你的进程起个名字

name 用于设置进程名,默认值是 None。

这里存在一个容易让人产生误解之处, 要明确, 默认值所呈现的情形是 None , 然而这并不等同于进程名就是 None。

你要是不传, 会自动给进程编号,从 1 开始:

if __name__ == "__main__": p1 = Process(target=speak) p2 = Process(target=speak) p1.start() p2.start() print(p1.name) # Process-1 print(p2.name) # Process-2

其输出呈现为 -1、-2 这样的情况, 仿佛公司在不给员工进行姓名设定时, HR 依据员工入职的先后顺序编排出一个号码。

想自定义名字,直接传就行:

p1 = Process(target=speak, name="说话进程") print(p1.name) # 说话进程

子进程怎么知道"我自己是谁"?

其上是于主进程之中读取子进程的称谓。而言那子进程自身可否读到自我的称谓, 是可以读到的。且可知道。

使用 ( ) 此种函数, 其为所给予的, 对之进行调用, 便能够获取到当下正处于运行状态的那个进程对象。

from multiprocessing import Process, current_process import time def speak(): print("--- 子进程开始 ---") # 在子进程内部,拿到自己,再读名字 print("我的名字是:", current_process().name) time.sleep(1) if __name__ == "__main__": p1 = Process(target=speak, name="说话进程") p1.start() p1.join()

输出:我的名字是: 说话进程。

记着这一规则: 于任意一个进程当中, 你若调用(), 所获取到的便是“当下正在运行的那个进程”。在子进程的函数之内进行调用, 所获取到的即为子进程自身;于主进程里进行调用, 所获取到的便是主进程。

在排查问题之际, 这个物件好用得很——你所运行的程序开启了8个进程, 日志当中尽是一模一样的输出内容, 完全没有办法分辨究竟是哪一条打印出来的。添加上进程名之后, 一眼便能实现定位。

五、args:按顺序递包裹(位置参数)

如果你想给 指向的函数传参数,就用 args。

一个元组是必须要传给args的, 元组之内的值依据顺序会对应到依据顺序的函数的形参之上。

from multiprocessing import Process import time def speak(a, b): print("a =", a) print("b =", b) time.sleep(1) if __name__ == "__main__": p1 = Process(target=speak, args=(666, 888)) p1.start() p1.join()

运行结果:

a = 666 b = 888

新手第一大坑:单个参数一定要加逗号

回到开头那位读者的问题。当你的函数只接收一个参数时:

# 错误写法:括号里只有一个值,Python 把它当成普通数字,不是元组 p = Process(target=speak, args=(666)) # 正确写法:加个逗号,它才是元组 p = Process(target=speak, args=(666,))

哪里存在区别呢? (666) 属于整数 666, 括号仅仅是起到装饰作用;(666,) 这才是仅有一个元素的元组。args 所要求的是元组, 然而你却给了一个整数, 其内部会对它进行遍历, 进而直接报错:

TypeError: 'int' object is not iterable

这个报错从字面上来理解, 意思是“整数不能够被进行遍历操作”, 看上去和参数之间, 完全没有任何关联, 故而进行查找时, 才会存在难度。我通过实际测试, 已经验证过了, 确实就是这一行代码引发的该报错。

记住口诀:元组只有一个元素时,逗号不能省。

六、:贴好标签的包裹(关键字参数)

被传递的是关键字参数, 因而它必然得写成字典的模样, 字典的 key 是函数的形参名, 而字典的 value 是要传递的值。

from multiprocessing import Process import time def speak(a, b, message): print("a =", a) print("b =", b) print("message =", message) time.sleep(1) if __name__ == "__main__": p1 = Process( target=speak, args=(666, 888), kwargs={"message": "你好,多进程"} ) p1.start() p1.join()

运行后 拿到的就是 你好,多进程。

能够同时使用 args 和 啦。通常来讲: 用 args 来放置必传的、顺序不会变动的参数 ; 用 去设置可选的、预置有 的参数。如此这般代码读起来就会更加清晰明了。

七、:守护进程标记(先记个名字)

用于标记当前进程是否为守护进程。

这个参数, 我们今天不会去展开它, 原因在于, 它值得被单独提取出来, 去讲述整整一篇。你需要先记住一件事情, 守护进程乃是那种, “主进程一旦结束就会被一同带走”的进程, 主进程并不会等待它完成工作。

后面, 我会单独撰写一篇, 将它详尽阐述清楚, 涵盖为何你的程序, 有时呈现出卡住而不再退出的情形, 和子进程为何会演变成孤儿的状况。

八、一张表总结

参数

作用

传什么

要不要传

group

兼容 ,无实际用途

永远 None

不传

子进程要执行的函数

函数名(不加括号)

必传

name

进程名

字符串

可选,不传自动编号

args

给 传位置参数

元组

可选

给 传关键字参数

字典

可选

是否为守护进程

布尔值

可选,后续详讲

九、完整示例代码

把上面讲过的全串起来,你可以直接复制运行:

from multiprocessing import Process, current_process import time def speak(a, b, message): print("--- 子进程开始 ---") print("a =", a) print("b =", b) print("message =", message) # 子进程内部读取自己的名字 print("我的名字是:", current_process().name) time.sleep(1) print("--- 子进程结束 ---") if __name__ == "__main__": # 自定义名字 + args 传位置参数 + kwargs 传关键字参数 p1 = Process( target=speak, name="说话进程", args=(666, 888), kwargs={"message": "你好,多进程"} ) # 不传 name,Python 自动分配 Process-2 p2 = Process( target=speak, args=(111, 222), kwargs={"message": "我是自动编号的"} ) p1.start() p2.start() # 主进程里也能读到子进程的名字 print("p1 的名字:", p1.name) print("p2 的名字:", p2.name) p1.join() p2.join() print("--- 主进程结束 ---")

我本地跑下来的真实输出(进程顺序每次可能略有不同):

p1 的名字: 说话进程 p2 的名字: Process-2 --- 子进程开始 --- a = 666 b = 888 message = 你好,多进程 我的名字是: 说话进程 --- 子进程结束 --- --- 子进程开始 --- a = 111 b = 222 message = 我是自动编号的 我的名字是: Process-2 --- 子进程结束 --- --- 主进程结束 ---

留意一下, p2没有传递name, 它被自动编了号, 编号是 -2, 然而p1使用的是我们自己所起的名字。

写在最后

有不少初学者存在困惑, 并非是由于多进程具备难度, 而是源于基础概念未被清晰讲解。

就这六个参数而言,真正对你操心之事有所要求的仅仅只有四个了: 一个是指定去做什么的事宜参数, 还有诸如像指定用什么去做的相关参数, 另外还有args参数, 以及方便于进行调试时能够让人辨认确认的name参数。说到group参数就大可以直接去无视它好了, 关于这个在下一篇当中再去讲解说明。

往后再度碰到“参数传不进去”这种报错之时, 首先得核查两件事情, 其一, 要看看args究竟是不是元组(倘若只是单个元素有没有加上逗号呀), 其二, 还要瞧瞧下面有没有添加if ==""了。若是这两条都处理好了, 八成好些问题就都没了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询