我正在尝试修改python脚本以运行Shell程序,我使用subprocess.call()这样做,如下所示:
def on_leftclick(self):
import subprocess
subprocess.call("mpc toggle", shell=True)
并且当我单击鼠标左键时出现此错误:
Could not parse JSON (lexical error: invalid char in json text.)
[这是在i3pystatus中完成的,该程序与i3bar(i3窗口管理器的一部分)连接,我已经修改了另一个脚本,并且可以正常工作,例如:
def on_upscroll(self):
import subprocess
subprocess.call("pamixer --increase 1 --allow-boost", shell=True)
此外,我尝试这样做:
import subprocess
subprocess.call("mpc toggle", shell=True)
在python shell中有效,所以我不明白问题出在哪里。
任何帮助将不胜感激。
这是由于在i3pystatus模块中执行此操作引起的:
subprocess.call("mpc toggle") # parameter shell=True or False, doesn't matter
因为默认情况下subprocess.call()函数将父进程的stdout
和stderr
文件句柄(即i3pystatus
)传递给新的子进程(mpc
),所以您mpc
调用的所有输出被转储到i3pystatus
自己的输出中。该输出应该是有效的JSON,但现在其中有大量意外的随机控制台。这导致i3pystatus
的输出无法解析为JSON。*
您有两个选择:
subprocess
捕获/处置子流程的输出处理:
def on_leftclick(self):
subprocess.call("mpc toggle", shell=True,
stdout=subprocess.DEVNULL)
或者,如果需要输出,则为subprocess.Popen():
def on_leftclick(self):
p = subprocess.Popen(['mpc', 'toggle'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
out, err = p.communicate()
retcode = p.returncode
run_through_shell
帮助程序i3pystatus为您提供了一个包装subprocess
的助手:i3pystatus.core.command.run_through_shell:
from i3pystatus.core.command import run_through_shell
def on_leftclick(self):
run_through_shell(["mpc", "toggle"])
或者,要让您的外壳程序执行命令解析,请给它一个字符串:
def on_leftclick(self):
run_through_shell("mpc toggle", enable_shell=True)
出于您自己的邪恶目的,您也可以轻松获得返回码和stdout / stderr输出:
def on_leftclick(self):
retcode, out, err = run_through_shell(["mpc", "toggle"])
为了公平起见,直到问了问题的第二年run_through_shell
才存在。 i3pystatus在代码库中同时使用了这两种方法。
TL; DR:确保您的子进程没有将输出喷入added in December 2014自己的输出,因为该输出必须是有效的JSON。
*可能无法在i3pystatus
中传递给json.loads(),但我尚未证明这一点。