Skip to main content
 首页 » 编程设计

python之没有 shell 转义序列的 git show/log,用于 python sh

2025年05月04日15langtianya

我正在使用 python 的 sh 编写 git 命令的脚本。例如,我做类似的事情

import sh 
git = sh.git.bake(_cwd='/some/dir/') 
 
project_hash = git('rev-parse', 'HEAD').stdout.strip() 
project_branch = git('rev-parse', '--abbrev-ref', 'HEAD').stdout.strip() 
project_date = git('log', '-1', '--pretty=format:%ci').stdout.strip() 

然后我将 project_hash、project_branch 和 project_date 写入数据库等。

问题是 git 有时会在其输出中添加 shell 转义序列。例如,

print(repr(project_hash)) 
print(repr(project_branch)) 
print(repr(project_date)) 

导致

'e55595222076bd90b29e184b6ff6ad66ec8c3a03' 
'master' 
'\x1b[?1h\x1b=\r2012-03-26 01:07:40 -0500\x1b[m\r\n\r\x1b[K\x1b[?1l\x1b>' 

前两个字符串没有问题,但最后一个,日期,有转义序列。

有什么办法可以摆脱这些,例如要求 git 不要输出任何转义序列?

我已经尝试使用 git log 命令的“--no-color”选项。那没有帮助。

我也很乐意在 python 本身中剥离它们,但我不知道如何。我试过 s.encode('ascii') 其中 s 是日期字符串。那没有什么不同。

Print stdout in Python without shell escape sequences解决了同样的问题。那里的建议是使用 python 的子进程而不是 sh。例如,我可以做

project_date = subprocess.check_output(["git", "log", "-1", "--pretty=format:%ci"], cwd='/some/dir/') 

和

print(repr(project_date)) 

给予

'2012-03-26 01:07:40 -0500' 

这当然是我想要的。但是,如果可能的话,我更愿意坚持使用 sh,因此想知道我是否可以使用 sh 避免转义序列。

有什么建议吗?

请您参考如下方法:

那些不是颜色序列,那些看起来像终端初始化序列。具体来说:

ESC [ ? 1 h ESC = 

是开启功能键模式的顺序

ESC [ ? 1 l ESC > 

是再次关闭它的顺序。这表明 git log 正在通过您的寻呼机运行。我不太确定为什么;通常当输出是管道时 git 会禁止使用寻呼机(至少 subprocess.Popen() 是这样,我认为 sh 是这样,尽管我有未使用 sh 模块)。

(暂停以查阅文档...)

啊哈!每sh module docs ,默认情况下,sh-module-run 命令的输出通过伪 tty。这是在欺骗 git 来运行你的寻呼机。

作为一个稍微肮脏的解决方法,你可以运行 git --no-pager log ... 来抑制寻呼机的使用,即使在使用 sh 运行时也是如此>。或者,您可以尝试使用 _tty_out=False 参数(同样,我没有使用过 sh 模块,您将不得不进行一些试验)。有趣的是,sh 模块文档底部的示例之一是 git!