Centos OS 上的不同进程的 UUID 保持不变,但在 Windows OS 上工作正常(每个进程流的 UUID)
UUID stayed the same for different processes on Centos OS, but works fine on Windows OS (UUID per Process flow)
我 运行 在 Python 3.9 中有两个源文件。 (文件很大...)
文件一(fileOne.py)
# ...
sessionID = uuid.uuid4().hex
# ...
文件二(fileTwo.py)
# ...
from fileOne import sessionID
# ...
文件二使用模块 multiprocessing 执行。
- 当我在我的本地机器上 运行 打印文件二中的 UUID 时,它始终是唯一的。
- 当我 运行 Centos OS 上的脚本时,它不知何故保持不变
- 如果我重启服务,UUID会改变一次。
我的问题:为什么这在本地(Windows OS)按预期工作,但在 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)
当您 运行 您的脚本时,它会生成 uuid 的新值,但是当您 运行 它在某些服务中时,您的代码与以下代码相同:
sessionID = 123 # simple constant
因此,要解决此问题,您可以尝试将代码包装到函数中,例如:
def get_uuid():
return uuid.uuid4().hex
在你的第二个文件中:
from frileOne import get_uuid
get_uuid()
您的谜语很可能是由多处理在不同操作系统中的工作方式引起的。你没有提到,但你的“运行 本地”肯定是 Windows 或 MacOS,而不是 Linux 或其他 Unix Flavor。
问题是 Linux 上的多处理(以及之前在 MacOS 上的多处理,但在 Python 3.8 上更改了它),在使用多处理时使用了系统 fork
调用:当前流程是“按原样”复制的,其所有定义的变量和 类 - 由于您的 sessionID
是在导入时定义的,因此它在所有子流程中保持不变。
Windows 缺少 fork
调用,并且 multiprocessing 求助于启动一个新的 Python 解释器,该解释器从当前进程重新导入所有模块(这导致另一个更常见的混淆的原因,其中任何不受条目 Python 文件上的 if __name__ == "__main__":
保护的代码被重新执行)。在您的情况下,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
(您也可以查看最近关于同一主题的问题:)
如果您需要为每个不同的进程提供跨文件的唯一 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()
(如果设置了 none,setdefault dict 方法负责提供新的 ID 值)
注意:以这种方式设置的注册表将最多保留主进程 ID(如果多进程正在使用 fork
模式)和它自己 - 没有兄弟姐妹的数据,因为每个进程都会保留它的自己的注册表副本。如果您需要一个有效的进程间字典(例如,它可以为所有进程保存一个实时注册表),您可能会更好地使用 redis(https://redis.io - 当然 Python 绑定之一有一个透明的 Python-mapping-over-redis,所以你不必担心它的语义)
我 运行 在 Python 3.9 中有两个源文件。 (文件很大...)
文件一(fileOne.py)
# ...
sessionID = uuid.uuid4().hex
# ...
文件二(fileTwo.py)
# ...
from fileOne import sessionID
# ...
文件二使用模块 multiprocessing 执行。
- 当我在我的本地机器上 运行 打印文件二中的 UUID 时,它始终是唯一的。
- 当我 运行 Centos OS 上的脚本时,它不知何故保持不变
- 如果我重启服务,UUID会改变一次。
我的问题:为什么这在本地(Windows OS)按预期工作,但在 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)
当您 运行 您的脚本时,它会生成 uuid 的新值,但是当您 运行 它在某些服务中时,您的代码与以下代码相同:
sessionID = 123 # simple constant
因此,要解决此问题,您可以尝试将代码包装到函数中,例如:
def get_uuid():
return uuid.uuid4().hex
在你的第二个文件中:
from frileOne import get_uuid
get_uuid()
您的谜语很可能是由多处理在不同操作系统中的工作方式引起的。你没有提到,但你的“运行 本地”肯定是 Windows 或 MacOS,而不是 Linux 或其他 Unix Flavor。
问题是 Linux 上的多处理(以及之前在 MacOS 上的多处理,但在 Python 3.8 上更改了它),在使用多处理时使用了系统 fork
调用:当前流程是“按原样”复制的,其所有定义的变量和 类 - 由于您的 sessionID
是在导入时定义的,因此它在所有子流程中保持不变。
Windows 缺少 fork
调用,并且 multiprocessing 求助于启动一个新的 Python 解释器,该解释器从当前进程重新导入所有模块(这导致另一个更常见的混淆的原因,其中任何不受条目 Python 文件上的 if __name__ == "__main__":
保护的代码被重新执行)。在您的情况下,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
(您也可以查看最近关于同一主题的问题:
如果您需要为每个不同的进程提供跨文件的唯一 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()
(如果设置了 none,setdefault dict 方法负责提供新的 ID 值)
注意:以这种方式设置的注册表将最多保留主进程 ID(如果多进程正在使用 fork
模式)和它自己 - 没有兄弟姐妹的数据,因为每个进程都会保留它的自己的注册表副本。如果您需要一个有效的进程间字典(例如,它可以为所有进程保存一个实时注册表),您可能会更好地使用 redis(https://redis.io - 当然 Python 绑定之一有一个透明的 Python-mapping-over-redis,所以你不必担心它的语义)