子进程更改目录

我想在子目录/超级目录中执行一个脚本(首先我需要在这个子目录/超级目录中)。我无法让 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 会抛出错误,我不知道为什么。无论我尝试进入一个现有的子目录或去一个目录(如上所述)-我总是以相同的错误结束。

205077 次浏览

您的代码尝试做的是调用一个名为 cd ..的程序。您需要的是调用一个名为 cd的命令。

但是 cd是一个内部的 shell

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

但这样做毫无意义。由于没有进程可以更改其他进程的工作目录(同样,至少在类 UNIX 操作系统上,但在 Windows 上也是如此) ,这个调用会让 subshell 更改其 dir 并立即退出。

你想要的可以通过 os.chdir()或者 subprocess命名参数 cwd来实现,它可以在执行子进程之前立即更改工作目录。

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

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

或者干脆

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

你想使用一个绝对路径到可执行文件,并使用 Popencwd kwarg 来设置工作目录。看看 医生

如「 cwd 」不是「无」 ,儿童的工作目录将改为「无」 在执行 cwd 之前,请注意不要考虑这个目录 在搜索可执行文件时,因此无法指定程序的路径 相对于慢性阻塞性肺疾病。

若要将 your_command作为子进程运行在不同的目录中,请将 cwd参数作为 “维姆的回答中暗示。”传递:

import subprocess


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

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

基于这个答案的另一个选项是: 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'))

subprocess.callsubprocess模块中的其他方法都有一个 cwd参数。

这个参数决定了执行流程的工作目录。

所以你可以这样做:

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

看看 Popen 构造函数文件

我猜现在你会这么做:

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

os.chdir

>>> import os
>>> import subprocess
>>> # Lets Just Say WE want To List The User Folders
>>> os.chdir("/home/")
>>> subprocess.run("ls")
user1 user2 user3 user4