Comment intégrer un code bash dans pyhton

AxelleF_11 Messages postés 5 Statut Membre -  
mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   -
Salut tout le monde, je cherche exécuter une commande bash par l'intermédiaire de python car je n'ai pas la possibilité d'installer le module OTB qui n'est pas compatible avec mon PC.
J'ai besoin de calculer des indices multispectraux par cette commande bash puis ensuite les intégrer à une matrice déjà existante. Mais pour le moment je n'arrive pas a faire fonctionner ma commande ...

Mon code est le suivant :

import os
import fnmatch

src_directory = "/run/media/afavro/Elements/Acquisitions_Copernicus2/1/S2/4_reflectance/"
dossier = os.listdir (src_directory)
print(dossier)

for fichier in dossier:
        print (fichier)
        ssrc_directory = "/run/media/afavro/Elements/Acquisitions_Copernicus2/1/S2/4_reflectance/" + fichier + "/"
        rasters = os.listdir (ssrc_directory) 
        print(rasters) 
    
    for img in rasters:
        print (img)

        INPUT_FOLDER = ssrc_directory
        print(INPUT_FOLDER)
            
        OUTPUT_FOLDER = "/run/media/afavro/Elements/Acquisitions_Copernicus2/1/S2/5_indices/" + fichier + "/"
        print(OUTPUT_FOLDER)
                   
        def findRasters (path, filter):
            for root, dirs, files in os.walk(path):
                for file in fnmatch.filter(files, filter):
                    yield file
          
        
        for raster in findRasters(INPUT_FOLDER, '*.hdr'):
            print(raster)
            inRaster = ssrc_directory + raster
            print(inRaster)
            outRaster = OUTPUT_FOLDER + 'indices2_' + img
            print (outRaster)
            cmd = 'otbcli_RadiometricIndices -in inRaster -list Soil:BI Vegetation:MSAVI Vegetation:SAVI -out outRaster'         
            os.system(cmd)


En message d'erreur il m'est dit que l'image inRaster ne peut pas être ouverte mais je ne comprend pas pourquoi; Auriez-vous une idée ?

1 réponse

  1. mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   7 944
     
    Bonjour,

    Question préalable

    Quand tu dis que le module OTB n'est pas compatible avec ton PC, peux-tu clarifier (message d'erreur, etc) ?

    Sous Linux Ubuntu par exemple, ce module peut s'installer avec la commande sudo apt install
    python3-otb
    .

    En effet, passer par le module python sera plus propre que passer par une commande shell.

    Appeler une commande shell en python

    Personnellement, j'utilise plutôt
    Popen
    , cela permet en outre de récupérer les flux (sortie standard et sortie d'erreur) :

    Voici un exemple fonctionnel pour appeler graphviz, dans ton cas il suffirait d'adapter la valeur de la variable
    cmd
    , de renommer la fonction et de retravailler ses paramètres, le message d'erreur, et enfin de renommer la variable
    dot
    en par exemple
    otb
    :

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    from subprocess import Popen, PIPE
    
    def run_graphviz(s_dot, layout_engine = "dot", format = "svg") -> bytes:
        """
        Convert a dot string (graphviz format) into a graphic file.
        Args:
            s_dot: A string in the graphviz format.
            layout_engine: The graphviz engine used for the rendering.
                See "man dot" for more details.
            format: The output graphviz terminal.
                See "man dot" for more details.
        Returns:
            The bytes of the output image iff successful, None otherwise.
        """
        cmd = ['dot', '-T' + format, '-K', layout_engine]
        dot = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
        stdoutdata, stderrdata = dot.communicate(s_dot.encode("utf-8"))
        status = dot.wait()
        if status == 0:
            return stdoutdata.decode("utf-8")
        else:
            fstr = "dot returned {}\n[==== stderr ====]\n{}"
            print(fstr.format(status, stderrdata.decode('utf-8')))
            print("Input dot string was:\n%s\n" % s_dot);
            raise RuntimeError("run_graphviz: invalid string")


    Conseils concernant ton code
    • Déclarer une fonction dans une boucle n'est pas l'endroit le plus indiqué, mieux vaut la déclarer en début de fichier.
    • Pour améliorer la lisibilité de ton code, il serait préférable de déclarer tes variables globales (chemins...) en début de fichier et de leur donner un nom tout en capitales.
    • Généralement on met le programme principale dans une fonction (e.g.
      main
      ) ce qui permet par la suite de définir des points d'entrée (voir
      setup.py
      ).


    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    def main():
        # programme
    
    if __name__ == '__main__':
        main()
        sys.exit(0)


    Bonne chance
    0
    1. AxelleF_11 Messages postés 5 Statut Membre
       
      Je ne sais pas exactement pour quelles raisons otb ne peut être installer sur mon PC, l'informaticien de m'a structure n'y ai pas parvenu :/
      Super merci, je vais essayer avec ça !
      0
    2. AxelleF_11 Messages postés 5 Statut Membre
       
      voici le message d'erreur qui apparait quand je tente d'installer le module otb :

      Collecting package metadata: done
      Solving environment: failed

      PackagesNotFoundError: The following packages are not available from current channels:

      - python3-otb

      Current channels:

      - https://conda.anaconda.org/conda-forge/linux-64/
      - https://conda.anaconda.org/conda-forge/noarch/
      - https://conda.anaconda.org/r/linux-64/
      - https://conda.anaconda.org/r/noarch/
      - https://repo.anaconda.com/pkgs/main/linux-64/
      - https://repo.anaconda.com/pkgs/main/noarch/
      - https://repo.anaconda.com/pkgs/free/linux-64/
      - https://repo.anaconda.com/pkgs/free/noarch/
      - https://repo.anaconda.com/pkgs/r/linux-64/
      - https://repo.anaconda.com/pkgs/r/noarch/

      To search for alternate channels that may provide the conda package you're
      looking for, navigate to

      https://anaconda.org

      and use the search bar at the top of the page.
      0
    3. mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   7 944
       
      Attention, le nom que je t'ai donné correspond au paquet debian donc pour une installation avec
      apt
      ! Donc sous Debian/Ubuntu/... tu lancerais :

      sudo apt-get update
      sudo apt-get install python3-otb


      Dans ton cas tu as décidé de ne pas utilisé le python "standard" fourni par linux, mais d'installer anaconda. Cela signifie que tu as un 2e python installé, dans son répertoire propre, et avec ses modules propres.

      Comme tu l'as fait, il est naturel de passer par
      conda
      . Par contre, les paquets Conda ne sont nommés comme dans apt, mais plutôt comme dans python. Ici, en toute logique ce serait par exemple
      conda install otb
      . Malheureusement, ce paquet n'existe pas actuellement. À moins de trouver un dépôt anaconda on n'y arrivera pas comme ça.

      Si tu souhaites absolument utiliser conda, il faudra installer autrement.

      Méthode 1 : installation via le gestionnaire de paquets (recommandée)

      En admettant que tu sois sous debian/ubuntu :
      sudo apt-get update
      sudo apt-get install python3-otb


      Méthode 2 : installation manuelle

      On suit la procédure d'installation officielle :

      1) Installer les dépendances.

      Exemple sous debian/ubuntu :
      sudo apt-get update
      sudo apt-get install libx11-6 libxext6 libxau6 libxxf86vm1 libxdmcp6 libdrm2


      2) Installer otb :
      wget https://www.orfeo-toolbox.org/packages/OTB-6.6.1-Linux64.run
      chmod +x OTB-6.6.1-Linux64.run
      ./OTB-6.6.1-Linux64.run


      Rendre otb accessible avec le python fourni par anaconda

      À ce stade, tu devrais pouvoir faire marcher otb depuis ton interpréteur python standard :

      /usr/bin/python3


      Puis dans l'interpréteur :

      import otbApplication


      Tu peux notamment voir dans quels répertoire
      python3
      cherche ses modules :

      import os
      print(os.sys.path)


      Mais si tu lances juste
      python3
      , conformément à ce qui est retourné par la commande
      echo $PATH
      , c'est l'interpréteur d'anaconda qui sera lancé. Et si tu répètes les mêmes commandes, notamment afficher
      os.sys.path
      , tu verras qu'il ne cherche pas au mêmes endroits.

      Dès lors, deux manières de corriger.
      a) Soit tu rajoutes dans les répertoires de modules d'anaconda un lien symbolique vers l'endroit où est stocké otb (c'est ce que suggère la documentation officielle, avec la commande
      ln -s
      )
      b) Soit tu corriges la variable
      os.sys.path
      pour garantir qu'elle contient le bon répertoire.

      Bonne chance
      0