在 Centos 操作系统上不同进程的 UUID 保持不变,但在 Windows 操作系统上运行良好(每个进程流的 UUID)

问题描述 投票:0回答:2

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

文件一(fileOne.py)

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

文件二 (fileTwo.py)

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

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

  • 当我在本地计算机上运行并打印文件二中的 UUID 时,它始终是唯一的。
  • 当我在 Centos 操作系统上运行脚本时,它在某种程度上保持不变
  • 如果我重新启动服务,UUID 将更改一次。

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

更新1.0: 为了说清楚。

对于每个单独的进程,我需要 FileOne 和 FileTwo 中的 UUID 相同。这意味着

  • processOne = UUID in file one and in file two will be 1q2w3e
  • processTwo = UUID in file one and in file two will be r4t5y6 (a different one)
python multiprocessing uuid
2个回答
3
投票

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

问题在于,Linux 上的多处理(以及不久前在 MacOS 上的多处理,但在 Python 3.8 上进行了更改)在使用多处理时使用了系统

fork
调用:当前进程及其定义的所有内容都“按原样”复制变量和类 - 由于您的
sessionID
是在导入时定义的,因此它在所有子进程中保持不变。

Windows 缺少

fork
调用,并且多处理求助于启动一个新的 Python 解释器,该解释器从当前进程重新导入所有模块(这会导致另一个更常见的混乱原因,即任何不受
if __name__ == "__main__":
保护的代码)在条目上Python文件被重新执行)。在您的情况下,会重新生成
sessionID
的值。

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

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

(您还可以检查最近关于同一主题的问题:为什么在导入多处理的情况下使用 time.sleep 时,字符串打印 3 次而不是 1 次?

如果您需要为每个不同进程提供跨文件的唯一 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 (当然,其中一个 Python 绑定具有透明的 Python-mapping-over- redis,所以你不必担心它的语义)。


3
投票

当您运行脚本时,它会生成 uuid 的新值,但是当您在某些服务中运行它时,您的代码如下:

sessionID = 123 # simple constant

因此要解决此问题,您可以尝试将代码包装到函数中,例如:

def get_uuid():
    return uuid.uuid4().hex

在你的第二个文件中:

from frileOne import get_uuid

get_uuid()    
© www.soinside.com 2019 - 2024. All rights reserved.