Quiero ejecutar un script dentro de un subdirectorio / superdirectorio (primero necesito estar dentro de este sub / superdirectorio). No puedo subprocess
ingresar a mi subdirectorio:
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 arroja OSError y no sé por qué. No importa si trato de ir a un subdirectorio existente o subir un directorio (como arriba); siempre termino con el mismo error.
python
subprocess
ducin
fuente
fuente
os.chdir()
en su lugar.Respuestas:
Lo que su código intenta hacer es llamar a un programa llamado
cd ..
. Lo que quieres es llamar a un comando llamadocd
.Pero
cd
es un caparazón interno. Entonces solo puedes llamarlo comosubprocess.call('cd ..', shell=True) # pointless code! See text below.
Pero no tiene sentido hacerlo. Como ningún proceso puede cambiar el directorio de trabajo de otro proceso (de nuevo, al menos en un sistema operativo similar a UNIX, pero también en Windows), esta llamada hará que la subshell cambie su directorio y salga inmediatamente.
Lo que desea se puede lograr con
os.chdir()
o con elsubprocess
parámetro nombradocwd
que cambia el directorio de trabajo inmediatamente antes de ejecutar un subproceso.Por ejemplo, para ejecutar
ls
en el directorio raíz, puede hacerwd = os.getcwd() os.chdir("/") subprocess.Popen("ls") os.chdir(wd)
o simplemente
subprocess.Popen("ls", cwd="/")
fuente
cd
generalmente también existe como un binario, no solo como un shell integrado. El verdadero problema del OP era que estaba llamando a un binariocd ..
, sí. (Y su tercer párrafo habría sido su próximo problema, así que buena respuesta.)cd
poder funcionar como binario? No puede cantar el directorio de trabajo de su padre./usr/bin/cd
consiste enbuiltin cd "$@"
, por lo que también llama al shell incorporadocd
.cd
debe implementarse como comando de shell interno. No hay otra forma de hacerlo. Los comandos de shell internos se ejecutan dentro del mismo proceso que el shell. Lo que quise decir con subshell es el shell ejecutadoshell=True
. Obtiene el comando que se ejecutará, lo ejecuta y sale.Para ejecutar
your_command
como un subproceso en un directorio diferente, pase elcwd
parámetro, como se sugiere en la respuesta de @ wim :import subprocess subprocess.check_call(['your_command', 'arg 1', 'arg 2'], cwd=working_dir)
Un proceso hijo no puede cambiar el directorio de trabajo de su padre ( normalmente ). La ejecución
cd ..
en un proceso de shell secundario usando un subproceso no cambiará el directorio de trabajo de la secuencia de comandos Python principal, es decir, el ejemplo de código en la respuesta de @ glglgl es incorrecto .cd
es un shell incorporado (no un ejecutable separado), puede cambiar el directorio solo en el mismo proceso.fuente
Desea utilizar una ruta absoluta al ejecutable y utilizar el
cwd
kwarg dePopen
para establecer el directorio de trabajo. Consulte los documentos .fuente
subprocess.call(['ls', '-l'], cwd='/')
. Esto cambia el cwd ay/
luego se ejecutals
con-l
como argumento. Pero si quiero haceros.chdir('/')
y luegoopen('etc/fstab', 'r')
, no puedo reemplazaros.chdir()
con nada,subprocess.XXX(cwd='/')
ya que no ayudará, como se dijo. Estos son dos escenarios completamente diferentes.cwd=
según lo previsto. Yo también puedo hacerlosubprocess.call(['bin/ls', '-l'], cwd='/')
.subprocess.call
y otros métodos delsubprocess
módulo tienen uncwd
parámetro.Este parámetro determina el directorio de trabajo donde desea ejecutar su proceso.
Entonces puedes hacer algo como esto:
subprocess.call('ls', shell=True, cwd='path/to/wanted/dir/')
Consulte los documentos subprocess.popen-constructor
fuente
Otra opción basada en esta respuesta: https://stackoverflow.com/a/29269316/451710
Esto le permite ejecutar varios comandos (por ejemplo
cd
) en el mismo proceso.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'))
fuente
shell=True, executable='/bin/bash'
Supongo que en estos días harías:
import subprocess subprocess.run(["pwd"], cwd="sub-dir")
fuente
Si desea tener la funcionalidad de cd (asumiendo shell = True) y aún desea cambiar el directorio en términos del script de Python, este código permitirá que funcionen los comandos 'cd'.
import subprocess import os def cd(cmd): #cmd is expected to be something like "cd [place]" cmd = cmd + " && pwd" # add the pwd command to run after, this will get our directory after running cd p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) # run our new command out = p.stdout.read() err = p.stderr.read() # read our output if out != "": print(out) os.chdir(out[0:len(out) - 1]) # if we did get a directory, go to there while ignoring the newline if err != "": print(err) # if that directory doesn't exist, bash/sh/whatever env will complain for us, so we can just use that return
fuente
Si necesita cambiar de directorio, ejecute un comando y obtenga también la salida estándar:
import os import logging as log from subprocess import check_output, CalledProcessError, STDOUT log.basicConfig(level=log.DEBUG) def cmd_std_output(cd_dir_path, cmd): cmd_to_list = cmd.split(" ") try: if cd_dir_path: os.chdir(os.path.abspath(cd_dir_path)) output = check_output(cmd_to_list, stderr=STDOUT).decode() return output except CalledProcessError as e: log.error('e: {}'.format(e))
def get_last_commit_cc_cluster(): cd_dir_path = "/repos/cc_manager/cc_cluster" cmd = "git log --name-status HEAD^..HEAD --date=iso" result = cmd_std_output(cd_dir_path, cmd) return result log.debug("Output: {}".format(get_last_commit_cc_cluster()))
Output: "commit 3b3daaaaaaaa2bb0fc4f1953af149fa3921e\nAuthor: user1<[email protected]>\nDate: 2020-04-23 09:58:49 +0200\n\n
fuente
check_call
, mal.