子进程改变目录
- 2025-01-06 08:32:00
- admin 原创
- 97
问题描述:
我想在子目录/超级目录中执行脚本(我需要先进入这个子目录/超级目录)。我无法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,但我不知道为什么。无论我尝试进入现有子目录还是进入上一级目录(如上所示),我总是遇到相同的错误。
解决方案 1:
您的代码试图做的是调用一个名为 的程序cd ..
。您想要的是调用一个名为 的命令cd
。
但是cd
是 shell 内部的。因此你只能这样调用它
subprocess.call('cd ..', shell=True) # pointless code! See text below.
但这样做毫无意义。因为没有进程可以更改另一个进程的工作目录(再次强调,至少在类 UNIX 操作系统上是这样的,但在 Windows 上也是如此),此调用将使子 shell 更改其目录并立即退出。
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 ..
使用子进程在子 shell 进程中运行不会更改父 Python 脚本的工作目录,即@glglgl 答案中的代码示例是错误的。是 shell 内置命令(不是单独的可执行文件),它只能在同一cd
进程中更改目录。
解决方案 3:
subprocess.call
并且模块中的其他方法subprocess
都有一个cwd
参数。
此参数决定您想要执行进程的工作目录。
所以你可以做这样的事情:
subprocess.call('ls', shell=True, cwd='path/to/wanted/dir/')
查看文档subprocess.popen-constructor
解决方案 4:
您想使用可执行文件的绝对路径,并使用cwd
kwargPopen
来设置工作目录。请参阅文档。
如果 cwd 不为 None,则子进程的当前目录将在执行前更改为 cwd。请注意,在搜索可执行文件时不会考虑此目录,因此您无法指定相对于 cwd 的程序路径。
解决方案 5:
我想这些天你会这么做:
import subprocess
subprocess.run(["pwd"], cwd="sub-dir")
解决方案 6:
基于此答案的另一种选择: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'))
解决方案 7:
只需使用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
解决方案 8:
如果您想要拥有 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
解决方案 9:
如果您需要更改目录,请运行命令并获取 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
Author: user1<user1@email.com>
Date: 2020-04-23 09:58:49 +0200