python - 多進程 Value、Array應用記錄


在代碼優化的過程中,碰到了這樣一個問題:一個進程中我定義了幾個全局變量,然后我又Process了幾個子進程,子進程中是否可以各自對全局變量進行修改?最后全局變量會取哪個值呢?

 

經過一番嘗試以后得到結果:

  子進程繼承父進程的全局變量,而且是以復制的形式完成,所以子進程修改后的全局變量只對自己和自己的子進程有影響。

  父子進程不共享這些全局變量,也就是說:父進程中對全局變量的修改不影響子進程中的全局變量,同理,子進程也不影響父進程的。

 

為了實現父子進程的通信,在網上經過了一番翻找以后,找到了 Value和Array 方法

  Value函數返回一個shared memory包裝類,其中包含一個ctypes對象

    一般 整數用 i, 字符用 c,浮點數用 d 就可以了

 

  Array函數返回一個shared memory包裝類,其中包含一個數組,字符串需要用 Array 來傳遞

  • @args shared memory 中包含的值
  • @lock 默認值是True:創建一個新的lock來控制對value的訪問。該參數也可以是 multiprocessing.Lock 或 multiprocessing.RLock 對像,用來控制對value的訪問

================================================================================================================================  

案例一:

def worker(num, mystr, arr):
    num.value *= 2
    mystr.value = "ok"
    for i in range(len(arr)):
        arr[i] = arr[i] * (-1) + 1.5
 
def dump_vars(num, mystr, arr):
    print 'num: ', num.value
    print 'str: ', mystr[:]
    print 'arr: ', arr[:]
 
if __name__=='__main__':
    num = Value('i', 5)
    mystr = Array('c', 'just for test')
    arr = Array('d', [1.0, 1.5, -2.0])
    dir(str)
    print 'init value'
    dump_vars(num, mystr, arr)
 
    ps = [Process(target=worker, args=(num, mystr, arr)) for x in range(3)]
    for p in ps:
        p.start()
    for p in ps:
        p.join()
 
    print
    print 'after all workers finished'
    dump_vars(num, mystr, arr)
#結果:
init value
num:  5
str:  just for test
arr:  [1.0, 1.5, -2.0]

after all workers finished
num:  40
str:  ok

多次測試我發現,在共享字符串的時候,在主進程中的初始化決定了這個字符串的長度,
創建后字符串的長度固定不變,相當於把這個字符串所在的地址復制給一個指針,並且在字符串的首地址記錄了自身的長度,
在以后讀取這個值的時候就會去讀取那一段固定長度的內容,而不管現在的新內容長度是多少,舉個例子:
比如我們在主進程初始化一段字符串 "abcde",一旦初始化,長度就固定了,現在長度是5,然后我們在其他進程賦值,我們嘗試賦值為
"abcdefg",此時執行會報錯,因為長度超標了,我們在賦值為 "yes",最后輸出結果為 "yes&efg"(此處的&是代表一個不可顯示的字符,不同的環境下顯示不同,有可能顯示空格,有可能顯示null)。也就是說長短都不行,必須和初始化字符串等長。
於是得出這樣一個結論,如果你要共享一個字符串,那么在子進程中賦值時必須賦值長度相當的字符串。建議在子進程中可以先檢查字符串長度,然后在根據需要拼接指定長度的字符串

 

 

案例二:

from multiprocessing import Process, Value, Array

def f(n, a):
    n.value = n.value + 1
    for i in range(len(a)):
        a[i] = a[i] * 10

if __name__ == '__main__':
    num = Value('i', 1)
    arr = Array('i', range(10))

    p = Process(target=f, args=(num, arr))
    p.start()
    p.join()

    print(num.value)
    print(arr[:])
   
    p2 = Process(target=f, args=(num, arr))
    p2.start()
    p2.join()

    print(num.value)
    print(arr[:])

# the output is :
# 2
# [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
# 3
# [0, 100, 200, 300, 400, 500, 600, 700, 800, 900]

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM