web-dev-qa-db-fra.com

Répertoire de changement de sous-processus

Je veux exécuter un script dans un sous-répertoire/superdirectory (je dois d'abord être dans ce sous/super-répertoire). Je ne peux pas obtenir subprocess entrer dans mon sous-répertoire:

tducin@localhost:~/Projekty/tests/ve$ python
Python 2.7.4 (default, Sep 26 2013, 03:20:26) 
[GCC 4.7.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> import os
>>> os.getcwd()
'/home/tducin/Projekty/tests/ve'
>>> subprocess.call(['cd ..'])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/subprocess.py", line 524, in call
    return Popen(*popenargs, **kwargs).wait()
  File "/usr/lib/python2.7/subprocess.py", line 711, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1308, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

Python lance OSError et je ne sais pas pourquoi. Peu importe si j'essaie d'aller dans un sous-répertoire existant ou d'aller dans un répertoire (comme ci-dessus) - je finis toujours avec la même erreur.

66
ducin

Ce que votre code tente de faire, c'est d'appeler un programme nommé cd ... Ce que vous voulez, c'est appeler une commande nommée cd.

Mais cd est un shell interne. Donc, vous ne pouvez l'appeler que

subprocess.call('cd ..', Shell=True) # pointless code! See text below.

Mais c'est inutile de le faire. Comme aucun processus ne peut changer le répertoire de travail d'un autre processus (encore une fois, au moins sur un système d'exploitation de type UNIX, mais aussi sur Windows), cet appel subira le changement de sous-shell. son dir et sortir immédiatement.

Ce que vous voulez peut être réalisé avec os.chdir() ou avec le paramètre nommé subprocess nommé cwd qui modifie le répertoire de travail immédiatement avant l'exécution d'un sous-processus.

Par exemple, pour exécuter ls dans le répertoire racine, vous pouvez soit faire

wd = os.getcwd()
os.chdir("/")
subprocess.Popen("ls")
os.chdir(wd)

ou simplement

subprocess.Popen("ls", cwd="/")
99
glglgl

Courir your_command en tant que sous-processus dans un répertoire différent, transmettez le paramètre cwd en tant que suggéré dans la réponse de @ wim :

import subprocess

subprocess.check_call(['your_command', 'arg 1', 'arg 2'], cwd=working_dir)

Un processus enfant ne peut pas changer le répertoire de travail de son parent ( normalement ). Fonctionnement cd .. dans un processus shell enfant utilisant un sous-processus ne changera pas votre parent Python, c.-à-d., l'exemple de code dans la réponse de @ glglgl est erroné . cd est un shell intégré (et non un exécutable séparé), il ne peut changer de répertoire que dans le même processus .

40
jfs

Vous souhaitez utiliser un chemin absolu vers l'exécutable et utiliser le cwd kwarg de Popen pour définir le répertoire de travail. Voir le docs .

Si cwd n’est pas None, le répertoire actuel de l’enfant sera remplacé par cwd avant son exécution. Notez que ce répertoire n’est pas pris en compte lors de la recherche du fichier exécutable. Vous ne pouvez donc pas spécifier le chemin du programme par rapport à cwd.

24
wim

subprocess.call et les autres méthodes du module subprocess ont un paramètre cwd.

Ce paramètre détermine le répertoire de travail dans lequel vous souhaitez exécuter votre processus.

Donc, vous pouvez faire quelque chose comme ça:

subprocess.call('ls', Shell=True, cwd='path/to/wanted/dir/')

Consultez la documentation subprocess.popen-constructor

10
l__flex__l

Une autre option basée sur cette réponse: https://stackoverflow.com/a/29269316/45171

Cela vous permet d’exécuter plusieurs commandes (par exemple, cd) dans le même processus.

import subprocess

commands = '''
pwd
cd some-directory
pwd
cd another-directory
pwd
'''

process = subprocess.Popen('/bin/bash', stdin=subprocess.PIPE, stdout=subprocess.PIPE)
out, err = process.communicate(commands.encode('utf-8'))
print(out.decode('utf-8'))
7
Eyal Levin