[Risolto][Python] Terminare tutti i processi dello stesso gruppo

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
rai
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2848
Iscrizione: domenica 11 maggio 2008, 18:03
Desktop: plasma
Distribuzione: 22.04
Località: Palermo

[Risolto][Python] Terminare tutti i processi dello stesso gruppo

Messaggio da rai »

Voglio programmaticamente aprire e/o chiudere una finestra per visualizzare dei pdf.
Per ora sto usando

Codice: Seleziona tutto

(...)
# quando è richiesto aprire una finestra:
p = subprocess.Popen(["/usr/bin/okular", "/percorso/al/file.pdf"])
(...)
# appena è necessario chiuderla:
p.kill()
Vorrei rendere lo script DE-agnostico e invece dell' hard-code del visualizzatore potrei usare /usr/bin/xdg-open
ma in questo caso non saprei come chiudere la finestra del visualizzatore invocato a sua volta da xdg-open
Questo perchè p.kill() agisce sul processo col pid di xdg-open e non interferisce con il processo figlio
Cioè, quello che vorrei ottenere con python sarebbe l'equivalente in bash di:

Codice: Seleziona tutto

xdg-open /percorso/al/file.pdf & pid=$(pgrep -n xdg-open)
kill -15 -$pid
dove $pid è il pid di xdg-open e di tutto il suo gruppo di processi
man kill ha scritto:Negative PID values may be used to choose whole process groups
Qualcuno mi mostra un trucco per mandare un segnale a tutti i processi figli del sottoprocesso generato dallo script python?
Ultima modifica di rai il lunedì 23 maggio 2022, 19:49, modificato 1 volta in totale.
rai
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2848
Iscrizione: domenica 11 maggio 2008, 18:03
Desktop: plasma
Distribuzione: 22.04
Località: Palermo

Re: [Python] Terminare tutti i processi dello stesso gruppo

Messaggio da rai »

Continuerò a portare su aspettando che intervenga qualcuno con un'idea.
Mi accorgo di non avere postato un vero e proprio codice ma il problema è facilissimo da riprodurre con tre righe per chi vuole.
Eventualmente posterò dal PC più tardi qualcosa da copia-incollare.
Ho di nuovo riletto la documentazione di subprocess e non ci trovo spunti. Ci sarebbe il metodo send_signal() con cui si potrebbe inviare 1 cioè SIGHUP che, leggo, viene esteso a tutti i processi figli: ma il fatto è che, quando viene il momento di chiudere il visualizzatore, nel sistema non c'è più il processo di xdg-open di cui in Python abbiamo l'istanza
Avatar utente
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4446
Iscrizione: sabato 12 dicembre 2009, 20:58
Desktop: Mate
Distribuzione: Ubuntu Mate 22.04.1 LTS
Sesso: Maschile
Contatti:

Re: [Python] Terminare tutti i processi dello stesso gruppo

Messaggio da UbuNuovo »

Non mi intendo di Python, aspettando altri interventi...
Il tuo problema è trovare il pid del processo figlio, conoscendolo potresti ucciderlo?
Ho trovato un comando equivalente a pgrep ma di Python (get_pid).
Guarda se può esserti utile questa pagina: https://stackoverflow.com/questions/266 ... ocess-name
Salva l'Ucraina! 🇺🇦
Avatar utente
vaeVictis
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4703
Iscrizione: venerdì 27 luglio 2012, 17:58
Desktop: Gnome
Distribuzione: Ubuntu 20.04 64bit

Re: [Python] Terminare tutti i processi dello stesso gruppo

Messaggio da vaeVictis »

Pirates arrrrrrrrrrr awesome!!!
«I fear not the man who has practiced 10000 kicks once,
but I fear the man who has practiced one kick 10000 times.»
rai
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2848
Iscrizione: domenica 11 maggio 2008, 18:03
Desktop: plasma
Distribuzione: 22.04
Località: Palermo

Re: [Python] Terminare tutti i processi dello stesso gruppo

Messaggio da rai »

UbuNuovo ha scritto:
sabato 21 maggio 2022, 22:07
Non mi intendo di Python, aspettando altri interventi...
Il tuo problema è trovare il pid del processo figlio, conoscendolo potresti ucciderlo?
Ho trovato un comando equivalente a pgrep ma di Python (get_pid).
Guarda se può esserti utile questa pagina: https://stackoverflow.com/questions/266 ... ocess-name
Ciao, purtroppo lo script non conosce il nome con cui viene eseguito il processo dell'applicazione da killare, lo conosce solo il processo generato da python (è proprio il motivo per cui usare xdg-open)

PS non avevo visto la risposta di @vaeVictis che sembra puntuale. Me la leggo e ritorno
Avatar utente
vaeVictis
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4703
Iscrizione: venerdì 27 luglio 2012, 17:58
Desktop: Gnome
Distribuzione: Ubuntu 20.04 64bit

Re: [Python] Terminare tutti i processi dello stesso gruppo

Messaggio da vaeVictis »

Ci sono anche altre soluzioni. Come psutil.process.children
Pirates arrrrrrrrrrr awesome!!!
«I fear not the man who has practiced 10000 kicks once,
but I fear the man who has practiced one kick 10000 times.»
rai
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2848
Iscrizione: domenica 11 maggio 2008, 18:03
Desktop: plasma
Distribuzione: 22.04
Località: Palermo

Re: [Python] Terminare tutti i processi dello stesso gruppo

Messaggio da rai »

Grazie @vaeVictis, problema risolto usando os.setsid.
Non avevo trovato|considerato la pagina del tuo link dove viene riconosciuto il problema che ho descritto e in cui si dà la soluzione.
A dire la verità, la spiegazione che offre è un po' incasinata e il codice prevede l'esecuzione di un file signal_child.py inesistente in tutta la pagina.
Comunque, stringendo all'osso, bisogna passare a subprocess.Popen() il parametro opzionale preexec_fn in modo che prima del processo da generare (quello che nel mio caso è xdg-open) venga eseguito os.setsid(): questa chiamata di sistema fa in modo che tutti i "children" originati dal processo generato da Popen rientrino nello stesso gruppo e con l'id del processo "parent": così poi è facile terminarli

Codice: Seleziona tutto

#!/usr/bin/env python3 
import os, subprocess

il_pdf = '/percorso/a/un/file.pdf' # <<--- personalizzare ###

p = subprocess.Popen(['/usr/bin/xdg-open', il_pdf], preexec_fn=os.setsid)
input('Premi un tasto per chiudere la finestra del visualizzatore di PDF ')
os.killpg(p.pid, 15)  # questo modo e il seguente
#os.kill(-p.pid, 15)  # sono alternativi e equivalenti
Ci sono anche altre soluzioni. Come psutil.process.children
Avevo letto di psutil ma non lo avevo preso in considerazione perché comporta una ulteriore dipendenza. Allora avrei potuto installare PyQtWebEngine e mostrare i pdf in un widget, bypassando il visualizzatore di sistema.
Avatar utente
vaeVictis
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4703
Iscrizione: venerdì 27 luglio 2012, 17:58
Desktop: Gnome
Distribuzione: Ubuntu 20.04 64bit

Re: [Risolto][Python] Terminare tutti i processi dello stesso gruppo

Messaggio da vaeVictis »

Sì, quella documentazione è abbastanza caotica. Avevo notato anche io la mancanza di quel file, ma non pregiudicava la comprensione della modifica da fare (che è quella che hai indicato). Hai fatto bene a fare un sunto, io non avevo provveduto a cambiare link perché non vedendoti pensavo che sarebbe passato inosservato.

:ciao:
Pirates arrrrrrrrrrr awesome!!!
«I fear not the man who has practiced 10000 kicks once,
but I fear the man who has practiced one kick 10000 times.»
rai
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2848
Iscrizione: domenica 11 maggio 2008, 18:03
Desktop: plasma
Distribuzione: 22.04
Località: Palermo

Re: [Risolto][Python] Terminare tutti i processi dello stesso gruppo

Messaggio da rai »

Aggiungo che in realtà, per chi padroneggia le sottigliezze della shell (quindi non per me ;D), la documentazione di subprocess.Popen contiene diversi riferimenti (impliciti purtroppo) a come generare dal primo subprocess un child in una nuova sessione, cioè con lo stesso group id del subprocess che istanziamo. E infatti è stato introdotto un argomento fatto apposta, che quindi è quello consigliato invece di usare come avevo scritto preexec_fn=os.setsid
The start_new_session parameter can take the place of a previously common use of preexec_fn to call os.setsid() in the child.
...
If start_new_session is true the setsid() system call will be made in the child process prior to the execution of the subprocess. (POSIX only)
quindi l'esempio che avevo scritto prima diventa:

Codice: Seleziona tutto

#!/usr/bin/env python3 
import os, subprocess

il_pdf = '/percorso/a/un/file.pdf' # <<--- personalizzare ###

p = subprocess.Popen(['/usr/bin/xdg-open', il_pdf], start_new_session=True)
input('Premi un tasto per chiudere la finestra del visualizzatore di PDF ')
os.killpg(p.pid, 15)  # questo modo e il seguente
#os.kill(-p.pid, 15)  # sono alternativi e equivalenti
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: 0 utenti iscritti e 13 ospiti