scrivendo un file controller in Python

2

Ho bisogno di qualche consiglio sulla mia idea di scrivere un file controller in Python, e non come il controller di tipo C in MVC ma un'idea più semplice. Solo uno script Python che controlla l'operazione di alcuni altri script Python.

Descriverò l'idea e qualsiasi consiglio o idea sarebbe molto apprezzata.

Devo scrivere un sistema che faccia alcune attività in background per un'applicazione web. L'app Web è in PHP e separata dal sistema Python che sto scrivendo, Python eseguirà alcune attività automatiche e calcolerà e salverà alcuni dati analitici per l'app Web da utilizzare e visualizzare.

Ho esperienza con Python base ma non ho spinto in avanti per imparare molto su Python di classe / obiettivo. Finora quello che ho scritto per il sistema è un mucchio di script py separati che fanno i lavori che devono fare, scritti in modo totalmente procedurale. Funzionano tutti bene, ma non è ancora un sistema. Il mio krux iniziale era che dovevo tenerli tutti vivi e correre all'infinito sullo sfondo. Dopo alcune ricerche ho deciso che il modo migliore per farlo era avere un manager dei processi come Supervisord che si occupasse di ogni script, io avvii gli script e permetto loro di girare per un certo tempo con un ciclo finito (in ogni script) e poi uscivano, quindi il supervisore li riavviava ogni volta che uscivano e li tenevano in vita. Volevo evitare l'uso di loop infiniti a causa della possibilità di perdite di memoria (credo che consentire l'uscita del processo libera completamente la memoria associata a quel processo e prevenga le perdite). Non ho provato nulla di tutto ciò, è solo un concetto al momento.

Qualcosa che preferirei fare sarebbe avere uno script come controller del resto degli script e fare in modo che il supervisore si occupi solo del controller. Questo mi evita di dover aggiornare il file di configurazione dei supervisori ogni volta che aggiungo al sistema Python.

L'idea di base per il controller sarebbe quella di avere un loop fork di nuovi thread per ogni script / processo separato e quindi fare in modo che il controller attenda che tutti gli altri thread siano completati prima di consentire al ciclo di eseguire un'altra iterazione (riavviando tutto di nuovo) .

Immagino che quello che devo fare per questo sarebbe quello di avvolgere tutto il codice in ogni script in una funzione, quindi importarli come moduli nel controller e chiamare ogni funzione su un nuovo thread all'interno del ciclo 'principale' del controller. Quindi il ciclo viene eseguito, chiama ogni funzione su un nuovo thread e attende che ogni thread finisca prima di ricominciare.

Come suona come un concetto?

L'unica domanda di codifica diretta che ho è di trasformare i miei script in moduli, come posso passare da un codice totalmente procedurale (senza funzioni, senza classi) in un modulo importabile? posso avvolgere le procedure solo in una funzione o devo anche averle in una classe?

    
posta jonathan 03.09.2015 - 16:08
fonte

2 risposte

2

Ho un sistema simile ma ho un concetto diverso:

  • Uso cron per avviare automaticamente i processi
  • Verifica se il processo correlato è in esecuzione
  • Se non è in esecuzione, avvia il processo.

Il modulo utilizza il pacchetto psutil per ottenere un elenco di processi in esecuzione, cercare il processo correlato e restituire se è presente nell'elenco oppure no. Ciò può sembrare pratico o non conforme al tuo caso d'uso però:

import psutil

class ProcessControl(object):
    """
    This program checks whether the given python file is running or not. If check_params flag is set as True, then
    it will be checked if an instance of the python file is running with all of the given paramters. If check_params
    flag sets as False, then the check will be made with only using the python file name and instances of the file
    running with different parameters will also be count.
    """
    def __init__(self, filename, *args):
        self.filename = filename
        self.args = args
        self.arg_num = len(args)

    def process_count(self, check_params):
        process_count = 0
        # Examine the process list to check if given process is running or not...
        for _prs in psutil.process_iter():
            try:
                _cmdline = _prs.cmdline()
            except TypeError:
                _cmdline = _prs.cmdline
            if len(_cmdline) >= 2 and "python" in _cmdline[0] and self.filename in _cmdline[1] and _prs.is_running():
                # We found an instance of the process that is running. Since This control function is triggered when
                # we run the python code, There would be at least one process (this one) which is running. Counting 2
                # or more processes means there is another instance which is still running when we trigger the python
                # code file
                if check_params:
                    # We also will check the parameters for the complete similarity
                    if len(_cmdline) == 2 + self.arg_num and all(str(_arg) in _cmdline[2:] for _arg in self.args):
                        process_count += 1
                    else:
                        # This is no match...
                        pass
                else:
                    process_count += 1
            else:
                # This is no match....
                pass
        return process_count

    def is_running(self, check_params=True):
        return self.process_count(check_params) > 1

Ho dei piccoli file python che hanno un codice simile come sotto:

Ex:

myFile.py

class MyCodeClass:
    def run_code(self):
         ...


if __name__ == "__main__":
    my_code = MyCodeClass()
    try:
        if ProcessControl(__file__).is_running():
            print "Already Running"
        else:
            my_code.run_code()
    except Exception as e:
        print e

E infine ho linee che attivano questo file nel mio cron :

* * * * * python myFile.py

Logic:

cron attiva questo file ogni x minuti. ProcessControl controlla se il file è in esecuzione o meno. Quando si chiama il metodo is_running , è possibile passare un valore bool in modo che il controllore ignori i parametri passati durante l'esecuzione del file python. Mi piace se check_params è True dopo che due comandi saranno accettati come diversi e saranno entrambi attivati:

python myOtherFile.py 127.0.0.1 220
python myOtherFile.py 127.0.0.1 250

e disabilitare check_params valuterà la seconda chiamata come lo stesso programma e non la innescherà

    
risposta data 14.09.2015 - 15:16
fonte
1

Penso che stai reinventando la shell. Basta creare uno script bash che controlli i tuoi moduli

I would start up the scripts and allow them to run for a certain time with a finite loop (in each script) and then they would exit, then the supervisor would restart them every time they exit and keep them alive

Questo è meglio con lo script di shell piuttosto che il threading / forking manualmente

UPD: dai un'occhiata a questo Q / A su stackoverflow :

until myserver; do echo "Server 'myserver' crashed with exit code $?. Respawning.." >&2 sleep 1 done

    
risposta data 09.09.2015 - 11:35
fonte

Leggi altre domande sui tag