Я хочу выполнить сценарий внутри подкаталога / суперкаталога (сначала мне нужно быть внутри этого подкаталога / суперкаталога). Я не могу subprocess
войти в свой подкаталог:
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 выдает OSError, и я не знаю почему. Не имеет значения, пытаюсь ли я перейти в существующий подкаталог или подняться на один каталог вверх (как указано выше) - я всегда получаю одну и ту же ошибку.
python
subprocess
Ducin
источник
источник
os.chdir()
вместо.Ответы:
Ваш код пытается вызвать программу с именем
cd ..
. Вам нужно вызвать команду с именемcd
.Но
cd
это оболочка внутренняя. Так что вы можете называть это только какsubprocess.call('cd ..', shell=True) # pointless code! See text below.
Но делать это бессмысленно. Поскольку ни один процесс не может изменить рабочий каталог другого процесса (опять же, по крайней мере, в UNIX-подобной ОС, но также и в Windows), этот вызов заставит подоболочку изменить свой каталог и немедленно выйти.
То, что вы хотите, может быть достигнуто с помощью
os.chdir()
или с помощьюsubprocess
указанного параметра,cwd
который изменяет рабочий каталог непосредственно перед выполнением подпроцесса.Например, для выполнения
ls
в корневом каталоге вы можете сделатьwd = os.getcwd() os.chdir("/") subprocess.Popen("ls") os.chdir(wd)
или просто
subprocess.Popen("ls", cwd="/")
источник
cd
обычно также существует как двоичный файл, а не только как встроенная оболочка. Настоящая проблема OP заключалась в том, что он вызывал двоичный файлcd ..
, да. (И ваш третий абзац был бы его следующей проблемой, так что хороший ответ.)cd
уметь работать как бинарник? Он не может изменять рабочий каталог своего родителя./usr/bin/cd
состоит изbuiltin cd "$@"
- поэтому он также просто вызывает встроенную оболочкуcd
.cd
должна быть реализована как внутренняя команда оболочки. Другого пути нет. Команды внутренней оболочки выполняются в том же процессе, что и оболочка. Под подоболочкой я имел в виду оболочку, для которой выполняетсяshell=True
. Он получает команду на выполнение, выполняет ее и завершает работу.Чтобы запустить
your_command
как подпроцесс в другом каталоге, передайтеcwd
параметр, как предлагается в ответе @wim :import subprocess subprocess.check_call(['your_command', 'arg 1', 'arg 2'], cwd=working_dir)
Дочерний процесс не может изменить рабочий каталог своего родителя ( обычно ). Запуск
cd ..
в дочернем процессе оболочки с использованием подпроцесса не изменит рабочий каталог вашего родительского скрипта Python, т.е. пример кода в ответе @ glglgl неверен .cd
является встроенной оболочкой (а не отдельным исполняемым файлом), он может изменять каталог только в том же процессе.источник
Вы хотите использовать абсолютный путь к исполняемому файлу и использовать
cwd
kwarg ofPopen
для установки рабочего каталога. См. Документы .источник
subprocess.call(['ls', '-l'], cwd='/')
. Это изменяет cwd на,/
а затем запускаетсяls
с-l
аргументом as. Но если я хочу сделать ,os.chdir('/')
а потомopen('etc/fstab', 'r')
, я не могу заменитьos.chdir()
ни с чем о ,subprocess.XXX(cwd='/')
как это не поможет, как сказал. Это два совершенно разных сценария.cwd=
по назначению. Я тоже могуsubprocess.call(['bin/ls', '-l'], cwd='/')
.subprocess.call
и другие методы вsubprocess
модуле имеютcwd
параметр.Этот параметр определяет рабочий каталог, в котором вы хотите выполнить свой процесс.
Итак, вы можете сделать что-то вроде этого:
subprocess.call('ls', shell=True, cwd='path/to/wanted/dir/')
Ознакомьтесь с документами subprocess.popen-constructor
источник
Другой вариант, основанный на этом ответе: https://stackoverflow.com/a/29269316/451710
Это позволяет вам выполнять несколько команд (например
cd
) в одном процессе.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'))
источник
shell=True, executable='/bin/bash'
Думаю, в наши дни вы бы сделали:
import subprocess subprocess.run(["pwd"], cwd="sub-dir")
источник
Если вы хотите иметь функциональность cd (при условии, что shell = True) и все же хотите изменить каталог с точки зрения сценария Python, этот код позволит работать командам 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
источник
Если вам нужно сменить каталог, запустите команду и также получите вывод std:
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<user1@email.com>\nDate: 2020-04-23 09:58:49 +0200\n\n
источник
check_call
, плохо.