Python中使用共享变量+信号量实现进程间的实时通信
多进程共享内存(如 multiprocessing.Value 和 multiprocessing.Array):
- 如果使用
multiprocessing模块创建共享变量,这些变量通常只在同一进程池中的进程之间共享。因此,不同的 Python 环境(即不同的 Python 解释器运行的环境)无法直接访问这些共享变量。 - 这种方式的共享变量一般是进程内的,不会跨环境工作。如果尝试在另一个 Python 环境中访问它,通常会抛出错误,提示该共享变量不存在或不可访问
共享内存(posix_ipc.SharedMemory):
- 如果使用的是
posix_ipc或类似的库创建共享内存,其他 Python 程序(在同一台计算机上)也可以通过相同的共享内存名称来访问该内存。这是因为共享内存是系统级的资源,不依赖于单个进程的生命周期。 - 只要所有程序都使用正确的名称并确保有访问权限,另一个 Python 环境(另一个Python解释器运行的Python文件)应该能够成功访问共享内存,不会出错。
方法一:使用Multiprocessing
【Python程序1中】
import ctypes
import posix_ipc
import multiprocessing
from multiprocessing import shared_memory
# 如果系统中已经存在名为 /semaphore1 的信号量对象,Python并不会重新初始化它,而是使用现有的信号量,
# 导致现有的信号量可能有残留状态,使得 acquire() 一直阻塞。
# 在创建信号量之前,先删除现有的同名信号量
try:
posix_ipc.unlink_semaphore("/semaphore1")
except posix_ipc.ExistentialError:
pass # 如果信号量不存在,忽略错误
# 创建具名信号量(其他进程可以使用同样的名称 "/semaphore1" 来访问),1表示有物品,0表示没物品
# 注意,需要intial_value = 1,这样信号量一开始才会有一个
# 使用 O_EXCL 标志来强制创建一个新的信号量
sem = posix_ipc.Semaphore("/semaphore1", flags=posix_ipc.O_CREAT | posix_ipc.O_EXCL, initial_value=1)
# 创建一个大小为 ctypes.c_int 所需的共享内存块
shm = shared_memory.SharedMemory(create=True, size=ctypes.sizeof(ctypes.c_int), name="steel")
# 使用 ctypes 将共享内存映射为一个整数
shared_int = ctypes.c_int.from_buffer(shm.buf)
sem.acquire() # 获取信号量
###########需要执行的操作 ####################
if (out1 == True):
# 检测到有输入
shared_int.value = 1
else:
shared_int.value = 0
############ 需要执行的操作 #####################
sem.release() # 释放信号量
# 释放共享内存
shm.close()
shm.unlink()
# 删除信号量(通常由创建信号量的进程负责清理)
sem.unlink()
【Python程序2中】
import posix_ipc
from multiprocessing import shared_memory, resource_tracker
import ctypes
# 链接信号量
sem = posix_ipc.Semaphore("/semaphore1")
# 连接到名为 "steel" 的共享内存块
shm = shared_memory.SharedMemory(name="steel")
# 使用 ctypes 将共享内存映射为一个整数
shared_int = ctypes.c_int.from_buffer(shm.buf)
# 取消资源跟踪,在另一个程序1中会释放这个共享内存
resource_tracker.unregister(shm._name, "shared_memory")
sem.acquire() # 获取信号量
########## 待执行操作#################################
if shared_int.value ==1:
message = "True"
else:
message = "False"
########### 待执行操作###############################
sem.release() # 释放信号量
方法二:使用Posix_ipc
【Python程序1中】
import posix_ipc
import mmap
import time
# 如果系统中已经存在名为 /semaphore1 的信号量对象,Python并不会重新初始化它,而是使用现有的信号量,
# 导致现有的信号量可能有残留状态,使得 acquire() 一直阻塞。
# 在创建信号量之前,先删除现有的同名信号量
try:
posix_ipc.unlink_semaphore("/semaphore1")
except posix_ipc.ExistentialError:
pass # 如果信号量不存在,忽略错误
# 创建具名信号量(其他进程可以使用同样的名称 "/semaphore1" 来访问),1表示有物品,0表示没物品
# 注意,需要intial_value = 1,这样信号量一开始才会有一个
# 使用 O_EXCL 标志来强制创建一个新的信号量
sem = posix_ipc.Semaphore("/semaphore1", flags=posix_ipc.O_CREAT | posix_ipc.O_EXCL, initial_value=1)
# 创建共享内存,指定名称和大小
shm = posix_ipc.SharedMemory("/my_shared_memory", flags=posix_ipc.O_CREAT, size=1024)
# 获取共享内存的内存缓冲区
memory = mmap.mmap(shm.fd, shm.size)
sem.acquire() # 获取信号量
# 向共享内存写入数据
memory[:5] = b'hello'
sem.release() # 释放信号量
# 关闭共享内存
memory.close()
shm.close_fd()【Python程序2中】
import posix_ipc
import mmap
# 链接信号量
sem = posix_ipc.Semaphore("/semaphore1")
# 打开已存在的共享内存
shm = posix_ipc.SharedMemory("/my_shared_memory")
memory = mmap.mmap(shm.fd, shm.size)
# 链接信号量
sem.acquire()
print(memory[:5]) # 输出 b'hello'
sem.release() # 释放信号量
# 关闭共享内存memory.close()
shm.close_fd()
浙公网安备 33010602011771号