簡體   English   中英

使用多處理和 time.strftime() 創建繪圖無法正常工作

[英]Creating plots with multiprocessing and time.strftime() doens't work properly

我正在嘗試使用多處理並行運行我的腳本來創建繪圖。 我在這里為我的問題創建了 2 個示例腳本,因為帶有計算部分的實際主腳本會太長。 在 script0.py 中,您可以看到我啟動實際 script1.py 的多處理部分,該部分並行執行 4 次。 在這個例子中,它只是創建了一些隨機散點圖。

腳本0.py:

import multiprocessing as mp
import os

def execute(process):
    os.system(f"python {process}")



if __name__ == "__main__":

    proc_num = 4
    process= []

    for _ in range(proc_num):
        process.append("script1.py")

    process_pool = mp.Pool(processes= proc_num)
    process_pool.map(execute, process)

腳本1.py:

#just a random scatterplot, but works for my example
    import time
    import numpy as np
    import matplotlib.pyplot as plt
    import os
    
    dir_name = "stackoverflow_question"
    plot_name = time.strftime("Plot %Hh%Mm%Ss")      #note the time.strftime() function
    
    if not os.path.exists(f"{dir_name}"):
        os.mkdir(f"{dir_name}")
    
    N = 50
    x = np.random.rand(N)
    y = np.random.rand(N)
    colors = np.random.rand(N)
    
    area = (30 * np.random.rand(N))**2
    
    plt.scatter(x,y, s=area, c=colors, alpha=0.5)
    #plt.show()
    plt.savefig(f"{dir_name}/{plot_name}", dpi = 300)

重要的是,我按其創建時間命名 plot

plot_name = time.strftime("繪圖 %Hh%Mm%Ss")

所以這會創建一個類似“Plot 16h39m22s”的字符串。 到目前為止一切順利......現在到我的實際問題,我意識到在並行啟動進程時。 有時 plot 名稱相同,因為 time.strftime() 創建的時間戳相同,因此可能會發生 script1.py 的一個實例覆蓋另一個已創建的 plot 的情況。

在我遇到這個確切問題的工作腳本中,我生成了大量數據,因此我需要根據它們的生成日期和時間來命名我的圖和 CSV。

我已經想過在 script1.py 被調用時給它一個變量,但我不知道如何實現這一點,因為我剛剛了解了多處理庫。 但是這個變量也必須改變,否則我會遇到同樣的問題。

有人對我如何實現這一點有更好的了解嗎? 非常感謝你。

我提出這些方法:

  • 方法 1:(簡單且推薦)如果您可以更改名稱,我建議使用 unixtime(例如使用 time.time() 或 time.time_ns())而不是日期或將小數添加到秒。 這樣你就幾乎不可能發生碰撞。
  • 方法2:在文件名中添加進程ID (例如:<filename_timestamp_processid>)。 這樣,即使兩個進程同時寫入,您也將擁有區分文件的進程 ID。 如果要在執行結束時從名稱中刪除 id,請讀取文件名並進行合並,如果有沖突,請以適當的方式調整文件名。
  • 方法 3:與方法 2 類似,但不是更改名稱,而是創建一個以進程 ID 命名的文件夾,在其中放置該進程的輸出。 在執行結束時,您合並文件夾並更正任何沖突。
  • 方法四:(不推薦,難管理,影響性能) 共享 memory 您在共享 memory 中使用帶有最后一個時間戳的變量,並檢查

歡迎來到本站。 幾個想法...

首先,您沒有遵循multiprocessing模塊中關於如何使用Pool的指南。 您應該在上下文管理器中with(...)...

那里有很多例子。 請參閱 dox 中的紅色警告:

https://docs.python.org/3/library/multiprocessing.html#module-multiprocessing.pool

此外,使用os.system調用有點奇怪/不安全。 為什么不將繪圖例程放入同一模塊或不同模塊中的標准 function 中並導入它? 這將允許您向 function 傳遞附加信息(如一個好的標簽)。 我希望像這樣的東西,其中source是數據文件或外部源......

def make_plot(source, output_file_name, plot_label):
    # read the data source
    # make the plot
    # save it to the output path...

就 label 而言,如果您在同一個“秒”內啟動這些進程,當然會有重疊,因此您可以選擇 append label 或類似進程號的其他信息數據源,或使用相同的時間戳,但將 output 放在唯一的文件夾中,如另一個答案中所建議的那樣。

我會想這樣的事情......

代碼:

from multiprocessing import Pool
import time

def f(data, output_folder, label):
    # here data is just an integer, in yours, it would be the source of the graph data...
    val = data * data
    # the below is just example...  you could just use your folder making/saving routine...
    return f'now we can save {label} in folder {output_folder} with value: {val}'

if __name__ == '__main__':
    with Pool(5) as p:
        folders = ['data1', 'data2', 'data3']
        labels = [time.strftime("Plot %Hh%Mm%Ss")]*3
        x_s = [1, 2, 3]
        output = p.starmap(f, zip(x_s, folders, labels))
        for result in output:
            print(result)

Output:

now we can save Plot 08h55m17s in folder data1 with value: 1
now we can save Plot 08h55m17s in folder data2 with value: 4
now we can save Plot 08h55m17s in folder data3 with value: 9

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM