Comment intégrer un code bash dans pyhton
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 :
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 ?
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
-
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 installpython3-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ôtPopen
, 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 variablecmd
, de renommer la fonction et de retravailler ses paramètres, le message d'erreur, et enfin de renommer la variabledot
en par exempleotb
:
#!/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 (voirsetup.py
).
#!/usr/bin/env python3 # -*- coding: utf-8 -*- def main(): # programme if __name__ == '__main__': main() sys.exit(0)
Bonne chance-
-
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. -
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 parconda
. 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 exempleconda 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épertoirepython3
cherche ses modules :
import os print(os.sys.path)
Mais si tu lances justepython3
, conformément à ce qui est retourné par la commandeecho $PATH
, c'est l'interpréteur d'anaconda qui sera lancé. Et si tu répètes les mêmes commandes, notamment afficheros.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 commandeln -s
)
b) Soit tu corriges la variableos.sys.path
pour garantir qu'elle contient le bon répertoire.
Bonne chance