Sebagai pemula dalam pemrograman, saya masih mendalami konsep multiprocessing dan multithreading.

Saya telah menulis skrip kecil yang membaca file dan menyalin file ke beberapa folder sementara dan melakukan tindakan berikut pada setiap folder.

  1. membangun label.
  2. Buat paket
  3. Dorong ke Nexus.

Ada ~500 folder & diproses secara berurutan. Bagaimana saya bisa menggunakan multiprocessing di sini, dengan demikian memproses 100 folder sekaligus secara paralel atau menambah jumlahnya. Juga, apakah mungkin untuk melacak proses tersebut dan gagal membangun bahkan satu sub proses gagal.

Saya membaca banyak artikel tentang multiprosesor, tetapi tidak dapat memahaminya :(

Setiap bimbingan akan sangat membantu saya, terima kasih.

folder1
   -- war file
   -- metadata

folder 2
   -- war file
   -- metadata
....
....

folder 500
   -- war file
   -- metadata

Cuplikan kode

import re, shutil, os
from pathlib import Path

target = "/home/work"
file_path = target + "/file.txt"

dict = {}
count = 1

def commands_to_run_on_each_folder(filetype, tmp_folder):
    target_folder = tmp_folder+'/tmp'+str(count)

    os.system(<1st command to build the label>)
    os.system(<2nd command to build the package>)
    <multiple file manipulations, where `filetype` is used and get the required file with right extension>
    <curl command to upload it to the Nexus>

#Read the text file and assemble it in a dictionary.
with open(file_path, 'r') as f:
    lines = f.read().splitlines()
    for i, line in enumerate(lines):
        match = re.match(r".*.war", line)
        if match:
            j = i-1 if i > 1 else 0
            for k in range(j, i):
                dict[match.string] = lines[k]
#Iterate the dictionary and copy the folder to the temporary folders.
for key, value in dict.items():
    os.mkdir(target+'/tmp'+str(count))
    shutil.copy(key, target+'/tmp'+str(count))
    shutil.copy(value, target+'/tmp'+str(count))
    commands_to_run_on_each_folder("war", target)
    count += 1

OS: Ubuntu 18.04 Memori: wadah 22 GB

0
Chel MS 21 September 2021, 17:03

1 menjawab

Jawaban Terbaik

Menggunakan concurrent.futures itu mudah. Saya telah memodifikasi skrip Anda menjadi:

#!/usr/bin/env python3
import itertools
import concurrent.futures
import logging
import pathlib
import re
import shutil


logging.basicConfig(
    level=logging.DEBUG,
    format="%(levelname)s:%(processName)s:%(message)s"
)


def worker(path1, path2, src, target, logger):
    logger.debug("Create dir %s", target)
    target.mkdir(exist_ok=True)

    logger.debug("Copy files")
    shutil.copy(src / path1, target / path1)
    shutil.copy(src / path2, target / path2)

    logger.debug("Additional commands to run on %s", target)
    # TODO: Add actions here
    # commands_to_run_on_each_folder(...)


def main():
    #Read the text file and assemble it in a dictionary.
    tasks = {}
    with open("file.txt", 'r') as f:
        lines = f.read().splitlines()
        for i, line in enumerate(lines):
            match = re.match(r".*.war", line)
            if match:
                j = i-1 if i > 1 else 0
                for k in range(j, i):
                    tasks[match.string] = lines[k]

    logger = logging.getLogger()
    # src: The directory where this script is
    src = pathlib.Path(__file__).parent
    with concurrent.futures.ProcessPoolExecutor() as executor:
        for taskid, (path2, path1) in enumerate(tasks.items(), 1):
            target = pathlib.Path(f"/tmp/dir{taskid}")

            # Calls `worker` function with parameters path1, path2, ...
            # concurrently
            executor.submit(worker, path1, path2, src, target, logger)


if __name__ == "__main__":
    main()

Berikut adalah contoh keluaran:

DEBUG:ForkProcess-1:Create dir /tmp/dir1
DEBUG:ForkProcess-1:Copy files
DEBUG:ForkProcess-1:Additional commands to run on /tmp/dir1
DEBUG:ForkProcess-1:Create dir /tmp/dir2
DEBUG:ForkProcess-1:Copy files
DEBUG:ForkProcess-1:Additional commands to run on /tmp/dir2
DEBUG:ForkProcess-1:Create dir /tmp/dir3
DEBUG:ForkProcess-1:Copy files
DEBUG:ForkProcess-1:Additional commands to run on /tmp/dir3
DEBUG:ForkProcess-1:Create dir /tmp/dir4
DEBUG:ForkProcess-1:Copy files
DEBUG:ForkProcess-1:Additional commands to run on /tmp/dir4

Catatan

  • Saya menggunakan logging daripada print karena logging bekerja lebih baik dengan lingkungan multi proses
  • Untuk mematikan logging, ubah level ke logging.WARN
  • Saya menggunakan pathlib karena lebih nyaman daripada os.path
  • Catatan: Panggilan submit tidak akan menunggu. Itu berarti jika fungsi worker membutuhkan waktu lama untuk dijalankan, submit akan segera kembali.
  • Menggunakan konstruksi with, pelaksana akan menunggu semua tugas bersamaan selesai sebelum keluar. Ini adalah apa yang Anda inginkan.
1
Hai Vu 21 September 2021, 21:18