Python 2.7 如何在不同进程之间共享字典中的更新值?
我是这里的新手,也是Python的新手。我有一个关于字典和多重处理的问题。我想在Raspberry Pi的第二个核心上运行这部分代码(第一个核心上运行的是GUI应用程序)。因此,我创建了一个字典(key(20)+数组,每个key的长度为256,下面的脚本只是一个简短的示例)。我在一个单独的脚本中初始化了这个字典,并将字典中的所有值置为零。脚本table1.py(此字典应可从两个核心获得) 在第二个脚本(应该在第二个内核上运行)中,我读取从串行端口获取的值,并根据适当的位置将它们放入/设置在这个字典中(解析+转换)。由于我通过串口获得了很多信息,所以信息一直在变化。脚本Readmode.pyPython 2.7 如何在不同进程之间共享字典中的更新值?,python-2.7,dictionary,serial-port,multiprocessing,Python 2.7,Dictionary,Serial Port,Multiprocessing,我是这里的新手,也是Python的新手。我有一个关于字典和多重处理的问题。我想在Raspberry Pi的第二个核心上运行这部分代码(第一个核心上运行的是GUI应用程序)。因此,我创建了一个字典(key(20)+数组,每个key的长度为256,下面的脚本只是一个简短的示例)。我在一个单独的脚本中初始化了这个字典,并将字典中的所有值置为零。脚本table1.py(此字典应可从两个核心获得) 在第二个脚本(应该在第二个内核上运行)中,我读取从串行端口获取的值,并根据适当的位置将它们放入/设置在这个字
from multiprocessing import Process
import time
import serial
import table1
def replace_all(text, dic):
for i, j in dic.iteritems():
text = text.replace(i, j)
return text
def hexTobin(hex_num):
scale = 16 ## equals to hexadecimal
num_of_bits = len(hex_num)*4
bin_num = bin(int(hex_num, scale))[2:].zfill(num_of_bits) #hex to binary
return bin_num
def readSerial():
port = "/dev/ttyAMA0"
baudrate = 115200
ser = serial.Serial(port, baudrate, bytesize=8, parity=serial.PARITY_NONE, stopbits=1, xonxoff=False, rtscts=False)
line = []
for x in xrange(1):
ser.write(":AAFF:AA\r\n:F1\r\n") # new
while True:
for c in ser.read():
line.append(c)
a=''.join(line[-2:])
if a == '\r\n':
b=''.join(line)
print("what I get:" + b)
c=b[b.rfind(":"):len(b)] #string between last ":" start delimiter and stop delimiter
reps = {':':'', '\r\n':''} #throw away start and stop delimiter
txt = replace_all(c, reps)
print("hex num: " + txt)
bina_num=hexTobin(txt) # convert hex to bin
print("bin num: " + bina_num)
ssbit = bina_num[:3] # first three bits
print("select first three bits: " + ssbit)
abit=int(ssbit,2) # binary to integer
if abit == 5:
table1.diction['FrameID'][0]=abit
if abit == 7:
table1.diction['FrameID'][5]=abit
print("int num: ",abit)
print(table1.diction)
line = []
break
ser.close()
p1=Process(target=readSerial)
p1.start()
在此期间,我想阅读这本词典中的信息,并在另一个过程中使用它们。但当我试着读取这些值时,它们都是零
我的问题是如何创建一个字典,该字典可用于这两个进程,并可根据从串行端口获取的数据进行更新?
提前感谢您的回答。在Python中,当您启动两个不同的脚本时,即使它们导入一些公共模块,它们也不会共享任何内容(除了代码)。如果两个脚本都
导入table1
,则它们都有自己的table1
模块实例,因此也有自己的table1.diction
变量实例
如果你想一想,一定是这样。否则,所有Python脚本将共享相同的sys.stdout
,例如。因此,在同时执行的两个不同脚本之间或多或少没有共享任何内容
多处理
模块允许您从同一个脚本创建多个进程。因此,您需要将GUI和读取函数合并到同一个脚本中。但是你可以做你想做的事。您的代码将如下所示:
import multiprocessing
# create shared dictionary sd
p1=Process(target=readSerial, args = (sd,)
p1.start()
# create the GUI behaviour you want
但是等一下。这也不行。因为当创建进程时,它会启动Python解释器的一个新实例,并再次创建它自己的所有实例,就像启动一个新脚本一样。因此,即使现在,默认情况下,readSerial
中的任何内容都不会与GUI进程共享
但幸运的是,多处理
模块提供了一些明确的技术来在进程之间共享数据。实现这一点的方法不止一种,但这里有一种可行的方法:
import multiprocessing
import time
def readSerial(d):
d["test"] = []
for i in range(100):
l = d["test"]
l.append(i)
d["test"] = l
time.sleep(1)
def doGUI(d):
while True:
print(d)
time.sleep(.5)
if __name__ == '__main__':
with multiprocessing.Manager() as manager:
sd = manager.dict()
p = multiprocessing.Process(target=readSerial, args=(sd,))
p.start()
doGUI(sd)
您会注意到,readSerial
函数中的列表追加有点奇怪。这是因为我们在这里使用的dictionary对象不是普通的dictionary。它实际上是一个字典代理,隐藏了一个用于在两个进程之间发送数据的管道。当我附加到字典内的列表时,需要通知代理(通过分配给字典),以便它知道通过管道发送更新的数据。这就是为什么我们需要赋值(而不是简单地在字典中直接改变列表)。有关这方面的更多信息,请查看。因为问题可能出在您的代码中,我们需要查看它才能找到答案。理想的情况是在一个简短的精简版本。你能给我提供信息,我如何使用这个字典,它有更多的键,每个键都有一个数组的值(如我的例子)?不知道为什么会有任何不同?共享字典是一个代理,但您可以像使用字典一样使用它:您对它所做的更改会传递回另一个进程,我已在答案中添加了一些详细信息,但如果您仍然被卡住,您需要向我显示哪些代码位仍然导致您出现问题。当我从串行端口读取数据时,我希望将它们放在指定的位置。示例:我使用frameID(这些ID始终在1到256之间)和其他信息获取帧。我想把这些数据总是放在同一个地方,所以如果frameID是124,我想把关于这个帧的所有信息写在同一个地方->dict{['Flag'][123]}=5,dict{['Dsc'][123]=“on”以此类推。在GUI中,我只需调用所需的键和数组中的位置。我希望这是可以理解的。如果在每个帧通过串行端口发送后我正确理解了这一点,我会在字典中添加一个额外的位置。因此,如果我得到1000帧,我将有1000个额外的位置(列)?所以,我需要某种程度上限制它?这些问题是在不同的主题上。问题是如何在两个进程之间共享词典。我建议您将迄今为止的代码放在一起,如果仍然卡住,请提出不同的问题。
import multiprocessing
import time
def readSerial(d):
d["test"] = []
for i in range(100):
l = d["test"]
l.append(i)
d["test"] = l
time.sleep(1)
def doGUI(d):
while True:
print(d)
time.sleep(.5)
if __name__ == '__main__':
with multiprocessing.Manager() as manager:
sd = manager.dict()
p = multiprocessing.Process(target=readSerial, args=(sd,))
p.start()
doGUI(sd)