Python 子进程更改目录
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21406887/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Subprocess changing directory
提问by ducin
I want to execute a script inside a subdirectory/superdirectory (I need to be inside this sub/super-directory first). I can't get subprocessto enter my subdirectory:
我想在子目录/超级目录中执行一个脚本(我需要先在这个子目录/超级目录中)。我无法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 throws OSError and I don't know why. It doesn't matter whether I try to go into an existing subdir or go one directory up (as above) - I always end up with the same error.
Python 抛出 OSError,我不知道为什么。无论我是尝试进入现有的子目录还是进入一个目录(如上所述)都没有关系 - 我总是以相同的错误告终。
采纳答案by glglgl
What your code tries to do is call a program named cd ... What you want is call a command named cd.
你的代码试图做的是调用一个名为cd ... 你想要的是调用一个名为cd.
But cdis a shell internal. So you can only call it as
但是cd是外壳内部。所以你只能称之为
subprocess.call('cd ..', shell=True) # pointless code! See text below.
But it is pointless to do so.As no process can change another process's working directory (again, at least on a UNIX-like OS, but as well on Windows), this call will have the subshell change its dir and exit immediately.
但这样做毫无意义。由于没有进程可以更改另一个进程的工作目录(同样,至少在类 UNIX 操作系统上,但在 Windows 上也是如此),因此该调用将使子 shell 更改其目录并立即退出。
What you want can be achieved with os.chdir()or with the subprocessnamed parameter cwdwhich changes the working directory immediately before executing a subprocess.
您可以使用os.chdir()或使用在执行子进程之前立即更改工作目录的subprocess命名参数来实现您想要的cwd。
For example, to execute lsin the root directory, you either can do
例如,要ls在根目录中执行,您可以执行
wd = os.getcwd()
os.chdir("/")
subprocess.Popen("ls")
os.chdir(wd)
or simply
或者干脆
subprocess.Popen("ls", cwd="/")
回答by wim
You want to use an absolute path to the executable, and use the cwdkwarg of Popento set the working directory. See the docs.
您想使用可执行文件的绝对路径,并使用cwdkwarg ofPopen来设置工作目录。请参阅文档。
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.
如果 cwd 不是 None,则在执行之前,子项的当前目录将更改为 cwd。请注意,搜索可执行文件时不考虑此目录,因此您不能指定程序相对于 cwd 的路径。
回答by jfs
To run your_commandas a subprocess in a different directory, pass cwdparameter, as suggested in @wim's answer:
要your_command在不同目录中作为子进程运行cwd,请按照@wim 的回答中的建议传递参数:
import subprocess
subprocess.check_call(['your_command', 'arg 1', 'arg 2'], cwd=working_dir)
A child process can't change its parent's working directory (normally). Running cd ..in a child shell process using subprocess won't change your parent Python script's working directory i.e., the code example in @glglgl's answer is wrong. cdis a shell builtin (not a separate executable), it can change the directory only in the sameprocess.
子进程不能更改其父进程的工作目录(通常)。cd ..使用subprocess在子 shell 进程中运行不会更改您的父 Python 脚本的工作目录,即@glglgl 的答案中的代码示例是错误的。cd是一个内置的 shell(不是一个单独的可执行文件),它只能在同一个进程中更改目录。
回答by Eyal Levin
Another option based on this answer: https://stackoverflow.com/a/29269316/451710
基于此答案的另一种选择:https: //stackoverflow.com/a/29269316/451710
This allows you to execute multiple commands (e.g cd) in the same process.
这允许您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'))
回答by l__flex__l
subprocess.calland other methods in the subprocessmodule have a cwdparameter.
subprocess.callsubprocess模块中的其他方法都有一个cwd参数。
This parameter determines the working directory where you want to execute your process.
此参数确定要在其中执行流程的工作目录。
So you can do something like this:
所以你可以做这样的事情:
subprocess.call('ls', shell=True, cwd='path/to/wanted/dir/')
Check out docs subprocess.popen-constructor
回答by Francois
I guess these days you would do:
我猜这些天你会这样做:
import subprocess
subprocess.run(["pwd"], cwd="sub-dir")
回答by Tactical Tux
If you want to have cd functionality (assuming shell=True) and still want to change the directory in terms of the Python script, this code will allow 'cd' commands to work.
如果您想拥有 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
回答by jturi
If you need to change directory, run a command and get the std output as well:
如果您需要更改目录,请运行命令并获取 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<[email protected]>\nDate: 2020-04-23 09:58:49 +0200\n\n

