首页 > 解决方案 > Centos 操作系统上不同进程的 UUID 保持不变,但在 Windows 操作系统上工作正常(每个进程流的 UUID)

问题描述

我有两个在 Python 3.9 中运行的源文件。(文件很大……)

文件一(fileOne.py)

# ...
sessionID = uuid.uuid4().hex
# ...

文件二(fileTwo.py)

# ...
from fileOne import sessionID
# ...

文件二使用模块多处理执行。

我的问题:为什么这可以按预期在本地(Windows 操作系统)工作,但不能在 CentOS 虚拟机上工作?

更新 1.0: 说清楚。

对于每个单独的进程,我需要 FileOne 和 FileTwo 的 UUID 相同。意思是说

标签: pythonmultiprocessinguuid

解决方案


您的谜题很可能是由多处理在不同操作系统中的工作方式引起的。您没有提到,但您的“本地运行”肯定是 Windows 或 MacOS,而不是 Linux 或其他 Unix Flavor。

问题是 Linux 上的多处理(直到前一段时间在 MacOS 上,但在 Python 3.8 上改变了它)fork在使用多处理时使用了系统调用:当前进程是“按原样”复制的,其中包含所有定义的变量和类 -由于您sessionID是在导入时定义的,因此它在所有子流程中都保持不变。

Windows 缺少fork调用,并且多处理求助于启动一个新的 Python 解释器,该解释器从当前进程重新导入所有模块(这会导致另一个更常见的混淆原因,其中任何不受if __name__ == "__main__":入口 Python 文件上的-执行)。在您的情况下,sessionID将重新生成 for 的值。

检查文档:https ://docs.python.org/3/library/multiprocessing.html#contexts-and-start-methods

因此,如果您希望变量在运行多处理时可靠地运行并且在所有进程中具有相同的值,您应该将其作为参数传递给其他进程中的目标函数,或者使用旨在跨进程共享值的适当结构如此处所述: https ://docs.python.org/3/library/multiprocessing.html#sharing-state-between-processes

(您还可以查看有关同一主题的这个最近的问题:Why is a string printing 3 times instead of 1 when using time.sleep with multiprocessing imports?

如果您需要每个不同进程的文件中的唯一 ID:( 从编辑和评论中更清楚)

有一个全局(普通)字典,它将作为每个进程的 ID 注册表,并使用函数来检索 ID - 该函数可以os.getpid()用作注册表的键。

文件 1:

import os
import uuid
...
_id_registry = {}

def get_session_id():
    return _id_registry.setdefault(os.getpid(), uuid.uuid4())

文件2:

from file1 import get_session_id

sessionID = get_session_id()

(如果没有设置,setdefault dict 方法负责提供新的 ID 值)

注意:以这种方式设置的注册表将最多保留主进程 ID(如果多处理正在使用fork模式)及其本身 - 没有兄弟姐妹的数据,因为每个进程都将拥有自己的注册表副本。如果您需要一个有效的进程间字典(例如,它可以为所有进程保存一个实时注册表),您可能会更好地使用 redis(https://redis.io - 当然其中一个 Python 绑定具有透明的Python-mapping-over-redis,所以你不必担心它的语义)


推荐阅读