Forum Programmation.python Recherche d'une liste dans une liste

Posté par . Licence CC by-sa
Tags : aucun
3
4
avr.
2017

Bonjour,

Je débute en Python, et j'aimerais explorer les subtilités du langage.

Dans le code suivant je veut lister tout les processus dont les noms correspondent à plusieurs critères.
J'ai trouvé deux façons de faire et je me demande s'il n'y a pas une façon plus élégante, optimal ou concise… ou, différente.

#!/bin/env python

from sys import exit
import psutil


procs=['gnome',
        'chrom']

def isRunning(x):
        for proc in procs:
                if x.name().find(proc) != -1: return(True)

def test1():
        for p in filter(isRunning , psutil.process_iter()):
                print((p.name(),p.pid))

def test2():
        for p in psutil.process_iter():
                for proc in procs:
                        if p.name().find(proc)!=-1:  print((p.name(),p.pid))

def main():
        test1()
        test2()
        return(0)

if __name__ == "__main__":
    exit(main())
  • # Éléments de réponses

    Posté par (page perso) . Évalué à 6.

    • Pas de parenthèse pour les return.
    • p.name().find(proc)!=-1 serait plus pythonique avec un simple proc in p.name()
    • Si tu gardes la version 1, tu peux écrire isRunning() de manière plus pythonique là encore:
    def isRunning(proc):
        pname = proc.name()
        return any(searched in pname for searched in procs)

    Au final tes 2 versions se valent pour un petit script ; après si tu écris beaucoup de code, tu voudras peut-être limiter le code boiler plate. Mais ça dépend de la tête de ton code et de ton imagination.
    Si tu passes ton temps à itérer sur les processus dont tu filtres le nom, tu pourrais par exemple faire un générateur:

    def filtered_procs(*name_parts):
        for p in psutil.process_iter():
            pname = p.name()
            if any(name_part in pname for name_part in name_parts):
                yield p
    
    for proc in filtered_procs('gnome', 'chrom'):
        print(p.name(), p.pid)

    Et si tu veux faire du beaucoup de filtrage et selon des critères variés, tu pourrais imaginer une API qui permettrait d'écrire des choses comme (inspiration Django):

    for proc in ProcessusSelector().filter(user='root').filter(Q(name__contains='gnome')|Q(name__contains='chrom')):
        print(p.name(), p.pid)
    • [^] # Re: Éléments de réponses

      Posté par . Évalué à 1.

      Merci,

      J'aime bien le mot pythonique ; canonique mais en python.

      Du coup je suis parti sur ta seconde proposition avec le générateur.

  • # Retour booléen

    Posté par (page perso) . Évalué à 4.

    Un commentaire sur ton isRunning().

    Si ta fonction trouve le processus, elle retourner un booléen True.
    Si le processus n'est pas trouvé elle ne fait pas de return, donc Python retourne None… même s'il est vrai qu'en cas d'utilisation dans un cast implicite vers booléens ça vaudra False, il serait mieux que ta fonction retourne explicitement False lorsque le processus n'est pas trouvé.

    Accessoirement, ça peut éviter de se retrouver à manipuler des valeurs non booléennes là où on en attendait:

    >>> v = None and (1==1)
    >>> print(v)
    None

    Python 3 - Apprendre à programmer en Python avec PyZo et Jupyter Notebook → https://www.dunod.com/sciences-techniques/python-3

    • [^] # Re: Retour booléen

      Posté par . Évalué à 1.

      Merci pour le commentaire, en effet les cast implicite ne sont pas l'idéal.

      La fonction any que je viens de découvrir permet d'éviter ce désagrément.

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.