Подтвердить что ты не робот

Изменение каталога подпроцесса

Я хочу выполнить script внутри подкаталога/суперкаталога (мне нужно сначала войти в этот суб/супер-каталог). Я не могу получить subprocess для ввода моего подкаталога:

[email protected]:~/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, и я не знаю почему. Неважно, пытаюсь ли я перейти в существующий subdir или перейти в один каталог вверх (как указано выше) - я всегда получаю ту же ошибку.

4b9b3361

Ответ 1

Что ваш код пытается сделать, это вызвать программу с именем 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="/")

Ответ 2

Чтобы запустить your_command в качестве подпроцесса в другом каталоге, передайте параметр cwd, как предложенный в ответ @wim:

import subprocess

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

Детский процесс не может изменить родительский рабочий каталог (обычно). Запуск cd .. в процессе дочерней оболочки с использованием подпроцесса не изменит ваш родительский Python script рабочий каталог, т.е. неправильный пример кода в ответе @glglgl. cd - это встроенная оболочка (не отдельный исполняемый файл), она может изменять каталог только в том же процессе.

Ответ 3

Вы хотите использовать абсолютный путь к исполняемому файлу и использовать cwd kwarg Popen для установки рабочего каталога. См. docs.

Если cwd не является None, текущий каталог childs будет изменен на cwd перед его выполнением. Обратите внимание, что этот каталог не рассматривается при поиске исполняемого файла, поэтому вы не можете указать путь к программам относительно cwd.

Ответ 4

subprocess.call и другие методы в модуле subprocess имеют параметр cwd.

Этот параметр определяет рабочий каталог, в котором вы хотите выполнить свой процесс.

Таким образом, вы можете сделать что-то вроде этого:

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

Ознакомьтесь с документами subprocess.popen-constructor

Ответ 5

Другая опция, основанная на этом ответе: fooobar.com/questions/133656/...

Это позволяет выполнять несколько команд (например, 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'))

Ответ 6

Я думаю, что в эти дни вы бы сделали:

import subprocess

subprocess.run(["pwd"], cwd="sub-dir")