我正在尝试Python多处理,我想使用Lock来避免重叠变量'es_id'值。
根据理论和示例,当进程调用lock时,'es_id'不能重叠,因为另一个进程无法访问它,但结果显示es_id经常重叠。
id值如何不重叠?
我的部分代码是:
def saveDB(imgName, imgType, imgStar, imgPull, imgTag, lock): #lock=Lock() in main
imgName=NameFormat(imgName) #name/subname > name:subname
i=0
while i < len(imgName):
lock.acquire() #since global es_id
global es_id
print "getIMG.pt:save information about %s"%(imgName[i])
cmd="curl -XPUT http://localhost:9200/kimhk/imgName/"+str(es_id)+" -d '{" +\
'"image_name":"'+imgName[i]+'", '+\
'"image_type":"'+imgType[i]+'", '+\
'"image_star":"'+imgStar[i]+'", '+\
'"image_pull":"'+imgPull[i]+'", '+\
'"image_Tag":"'+",".join(imgTag[i])+'"'+\
"}'"
try:
subprocess.call(cmd,shell=True)
except subprocess.CalledProcessError as e:
print e.output
i+=1
es_id+=1
lock.release()
...
#main
if __name__ == "__main__":
lock = Lock()
exPg, proc_num=option()
procs=[]
pages=[ [] for i in range(proc_num)]
i=1
#Use Multiprocessing to get HTML data quickly
if proc_num >= exPg: #if page is less than proc_num, don't need to distribute the page to the process.
while i<=exPg:
page=i
proc=Process(target=getExplore, args=(page,lock,))
procs.append(proc)
proc.start()
i+=1
else:
while i<=exPg: #distribute the page to the process
page=i
index=(i-1)%proc_num #if proc_num=4 -> 0 1 2 3
pages[index].append(page)
i+=1
i=0
while i<proc_num:
proc=Process(target=getExplore, args=(pages[i],lock,))#
procs.append(proc)
proc.start()
i+=1
for proc in procs:
proc.join()
执行结果屏幕:
结果是 subprocess.call(cmd,shell = True)的输出。我使用XPUT向ElasticSearch添加数据,es_id是数据的id。我希望这些id顺序增加而不重叠。 (因为如果它们重叠,它们将被之前的数据覆盖)
我知道XPOST不需要使用锁码,因为它会自动生成ID,但我需要在将来顺序访问所有数据(比如读取一行文件)。
如果你知道在使用XPOST后如何顺序访问所有数据,你能告诉我吗?
答案 0 :(得分:0)
您只提供了部分代码,因此我只能看到潜在的问题。对es_id
的一次访问进行锁定保护没有任何帮助。您必须在程序中出现的任何位置对其进行锁定保护 all 。也许最好为此目的创建一个访问函数,例如:
def increment_es_id():
global es_id
lock.acquire()
es_id += 1
lock.release()
可以从任何线程安全地调用它。
在您的代码中,将获取/释放调用尽可能紧密地移动到一起是一种很好的做法。在这里,您只需保护一个变量,因此您可以将获取/释放对移到es_id += 1
语句之前和之后..
更好的是在上下文管理器中使用锁(尽管在这种简单的情况下它不会有任何区别):
def increment_es_id2():
global es_id
with lock:
es_id += 1
答案 1 :(得分:0)
看起来您正在尝试使用锁访问全局变量,但全局变量是进程之间的不同实例。您需要使用的是共享内存值。这是一个有效的例子。它已经在Python 2.7和3.6上进行了测试:
from __future__ import print_function
import multiprocessing as mp
def process(counter):
# Increment the counter 3 times.
# Hold the counter's lock for read/modify/write operations.
# Keep holding it so the value doesn't change before printing,
# and keep prints from multiple processes from trying to write
# to a line at the same time.
for _ in range(3):
with counter.get_lock():
counter.value += 1
print(mp.current_process().name,counter.value)
def main():
counter = mp.Value('i') # shared integer
processes = [mp.Process(target=process,args=(counter,)) for i in range(3)]
for p in processes:
p.start()
for p in processes:
p.join()
if __name__ == '__main__':
main()
输出:
Process-2 1
Process-2 2
Process-1 3
Process-3 4
Process-2 5
Process-1 6
Process-3 7
Process-1 8
Process-3 9