Python的区别子流程.Popen有shell=True和一个真正的sh

2024-04-26 07:07:29 发布

您现在位置:Python中文网/ 问答频道 /正文

当我打开一个命令行时,我希望它在当前活动窗口所在的同一个工作目录中启动。 因此,我编写了一个python脚本,它可以找出正确的路径。它以打开终端的命令作为参数。在这个参数中,它用所需的目录替换占位符,并用

subprocess.Popen(cmd, stderr=subprocess.PIPE, shell=True)

字符串cmd正确组合为:

^{pr2}$

如果我在bash中执行这个命令,它会根据需要在正确的目录中打开xterm。 如果我从python脚本xterm doesnotopen执行此命令。在

区别在哪里?在


附加信息:

我使用的是python3.6.5。在

echo $SHELL返回/bin/bash。在

在i3配置中对脚本的键绑定:

^{3}$

(这个shell脚本只是一个简单的包装器,它将stderr重定向到日志文件以进行调试)

在bash xterm中执行以下命令后,即使从python也会打开:

xrdb -merge -I$HOME ~/.Xresources

Xresources中的相关行是

xterm*faceName: DejaVu Sans Mono Book

为什么会有不同呢?在


解决方案: 多亏了查尔斯·达菲的评论,我发现了问题所在。 在我的python脚本中,我用stderr=subprocess.PIPE重定向stderr,但我忘了读stderr。 在加载设置字体xterm的Xresources文件之前,会向stderr输出一个警告,提示无法加载字体。 xterm有一个非常小的缓冲区。因为我的程序没有读取stderr,所以缓冲区没有被清除,xterm被阻塞。在

替换

subprocess.Popen(cmd, stderr=subprocess.PIPE, shell=True)

p = subprocess.Popen(cmd, stderr=subprocess.PIPE, shell=True)
out, err = p.communicate()
sys.stderr.write(err)

会解决问题的。 但是因为我没有对stderr做任何事情,所以一开始就没有必要重定向它。 所以我现在用的是

subprocess.Popen(cmd, shell=True)

Tags: 命令目录脚本cmdbashtrue参数stderr
1条回答
网友
1楼 · 发布于 2024-04-26 07:07:29

不要使用shell=True;它不适合您的用例。在

import subprocess
try:
    from pipes import quote # Python 2
except ImportError:
    from shlex import quote # Python 3

dir='/mnt/data/software/computer/tools/i3'
p = subprocess.Popen(['xterm', '-e', 'cd %s && exec bash' % quote(dir)])

但是,您可以通过让subprocess.Popen为您设置目录来简化此操作:

^{pr2}$

也就是说,shell=True100%等同于运行sh -c '...command...',其中命令的文本在...command...;这正是它在实践中所做的。在


请注意,我删除了上面的stderr=subprocess.PIPE。您可以将其添加回,但前提是您的代码实际读取写入stderr的内容,例如调用communicate()。在

相关问题 更多 >