Index de l'article

Manage parallel scripts execution

You have some scripts working, OK.

Then another main script to control them all, OK.

You want to run it multiple times in parallel and have already verified that your code's logic allows it (handling shared directories, shared files, shared tables, etc.). Okay!

Put your main script in a .bat file, like this for example:

"C:\Program Files\MyPythonVersion.exe" "C:\Users\Georges\PycharmProjects\my_main_script.py"

Then, manage script execution choosing a maximum processus number and according the CPU and RAM available, example:

import subprocess
import psutil, time, sys, os
from termcolor import colored
from pathlib import Path
from sqlalchemy import create_engine, text
 
monFichierBat = userDirectory + 'PycharmProjects\\BDD_KF_v3\\FaisaibiliteAvancee\\AggregationParcelles\\auto.bat'
 
engineBasic = create_engine('mysql+mysqldb://%s:%s@%s:%i/%s' % (userDb, mdpDb, hostDb, portDb, maDb))
 
nbreTraitementMax = 3
pctgUsageRam = 70
pctgUsageCpu = 50
rafraichirSeconde = 1
 
# CONVERTIR OCTETS EN GIGAS
def octets_en_go(octets):
    return round(octets / (1024 ** 3), 2)
 
# BOUCLE INFINIE/TEMPS RÉEL
listeTraitementEnCours = []
while True:
 
    # USAGE MÉMOIRE
    print(colored('\n# USAGE MÉMOIRE', 'blue'))
 
    cpu = psutil.cpu_percent(interval=1)
    ram = psutil.virtual_memory()
 
    print('CPU utilisé à ' + str(cpu) + '%')
    print('RAM utilisée à ' + str(ram.percent) + '% (' + str(octets_en_go(ram.used)) + '/' + str(octets_en_go(ram.total)) + ' gigas)')
 
    # REGARDER S'IL Y A AU MOINS UNE DEMANDE EN ATTENTE
    checkSql = 'SELECT COUNT(*) AS nbr_wait FROM ma_table WHERE wait = 1 ;'
    with engineBasic.connect() as my_connection:
        nbrDemandeEnAttente = my_connection.execute(text(checkSql)).scalar()
 
    print(colored('\nActuellement ' + str(nbrDemandeEnAttente) + ' demande(s) en attente.', 'green'))
 
    # EXÉCUTER BAT (SANS ATTENDRE LA FIN DU PROCESS)
    # ET SOUS PLUSIEURS CONDITIONS
    if len(listeTraitementEnCours) < nbreTraitementMax and nbrDemandeEnAttente > 0 and cpu < pctgUsageCpu and ram.percent < pctgUsageRam :
        print(colored('\n# EXÉCUTER BAT (SANS ATTENDRE LA FIN DU PROCESS)', 'blue'))
        process = subprocess.Popen(monFichierBat, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
    print('Traitement lancé dans le PID:', process.pid)
 
    # LISTER LE TRAITEMENT EN COURS
    listeTraitementEnCours.append(process)
 
    # METTRE À JOUR LES TRAITEMENTS EN COURS
    print(colored('\nMETTRE À JOUR LES TRAITEMENTS EN COURS', 'blue'))
    for p in listeTraitementEnCours[:]:
        statut = p.poll()
        if statut is None:
            print('Le PID', p.pid, 'est en cours.')
        elif statut == 0:
            listeTraitementEnCours.remove(p)
            print(colored('Le PID ' + str(p.pid) + ' est terminé avec succès.', 'green'))
        else:
            listeTraitementEnCours.remove(p)
            print(colored('Le PID ' + str(p.pid) + ' est terminé avec une erreur :\n', statut, 'red'))
 
    print(colored('\nActuellement ' + str(len(listeTraitementEnCours)) + ' traitement(s) F2A en cours.', 'green'))
 
    time.sleep(rafraichirSeconde)

 

Liens ou pièces jointes
Télécharger ce fichier (France-Departements-Deformation.zip)France-Departements-Deformation.zip[France-Departements-Deformation]335 Ko
Télécharger ce fichier (simple_countries.zip)simple_countries.zip[simple_countries]1880 Ko