关于python:子进程更改目录

Subprocess changing directory

我想在子目录/超级目录中执行一个脚本(我需要先在这个子/超级目录中)。 我无法让subprocess进入我的子目录:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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,我不知道为什么。 无论我是尝试进入现有的子目录还是上一个目录(如上所述) - 我总是会遇到同样的错误。


您的代码尝试执行的操作是调用名为cd ..的程序。你想要的是调用名为cd的命令。

但是cd是一个shell内部。所以你只能称之为

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

但这样做毫无意义。由于没有进程可以更改另一个进程的工作目录(同样,至少在类UNIX操作系统上,但在Windows上),此调用将使子shell更改其目录并立即退出。

您可以使用os.chdir()subprocess命名参数cwd来实现所需的功能,该参数在执行子进程之前立即更改工作目录。

例如,要在根目录中执行ls,您可以执行此操作

1
2
3
4
wd = os.getcwd()
os.chdir("/")
subprocess.Popen("ls")
os.chdir(wd)

或者干脆

1
subprocess.Popen("ls", cwd="/")


要在另一个目录中运行your_command作为子进程,请传递cwd参数,如@wim的回答中所示:

1
2
3
import subprocess

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

子进程无法更改其父进程的工作目录(通常)。使用子进程在子shell进程中运行cd ..不会更改父Python脚本的工作目录,即@ glglgl的答案中的代码示例是错误的。 cd是一个shell内置(不是单独的可执行文件),它只能在同一进程中更改目录。


您希望使用可执行文件的绝对路径,并使用cwd kwarg of Popen来设置工作目录。查看文档。

If cwd is not None, the child’s current directory will be changed to
cwd before it is executed. Note that this directory is not considered
when searching the executable, so you can’t specify the program’s path
relative to cwd.


subprocesssubprocess模块中的其他方法具有cwd参数。

此参数确定要在其中执行进程的工作目录。

所以你可以这样做:

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

查看docs subprocess.popen-constructor


基于这个答案的另一种选择:https://stackoverflow.com/a/29269316/451710

这允许您在同一进程中执行多个命令(例如cd)。

1
2
3
4
5
6
7
8
9
10
11
12
13
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'))