python 中的彩色终端并排差异
color terminal side-by-side diffs broken in python
我正在尝试构建一个 python 应用程序以在 python 中快速生成颜色并排差异。我的问题是我可以从 linux CLI 并排生成,但是无论我尝试过什么命令处理(请参阅下面的尝试),差异在 python 下都会失败。
这是 正确的行为 如果我 运行 来自 linux CLI 的差异(在 wsltty
). Note that I get the same output from PuTTY
下:
当我 运行 来自 python 脚本的差异时,这是典型的 不需要的行为 ...
问题:
- 为什么下面的 python 尝试无法生成并排差异?
- 我可以做什么(在 python 下)来尽可能地从 CLI(上面的屏幕截图)呈现输出?
下面的 python 脚本包含了我试图让 python 渲染并排差异工作的尝试...简而言之,我已经尝试了很多次Popen()
,以及 subprocess.run()
和 os.system()
...
# filename: test_ydiff.py
from subprocess import run, Popen, PIPE
import shlex, os, pydoc
TEST_01 = True
TEST_02 = True
TEST_03 = True
if TEST_01:
cmd_01_input = "diff -u f_01.txt f_02.txt"
cmd_01_output = "ydiff -s"
proc_01_input = Popen(shlex.split(cmd_01_input),
stdout=PIPE)
proc_01_output = Popen(shlex.split(cmd_01_output),
stdin=proc_01_input.stdout, stdout=PIPE)
stdout_str, stdin_str = proc_01_output.communicate()
print(stdout_str.decode('utf-8'))
if TEST_02:
cmd_02_shell = "diff -u f_01.txt f_02.txt | ydiff -s"
proc_02_shell = Popen(cmd_02_shell, shell=True, stdout=PIPE)
stdout_str, stdin_str = proc_02_shell.communicate()
print(stdout_str.decode('utf-8'))
if TEST_03:
run("/usr/bin/diff -u ./f_01.txt ./f_02.txt|/home/mpennington/venv/py37_u18/bin/ydiff -s")
要比较的第一个文本文件:
# filename: f_01.txt
!
interface Ethernet0/0
ip address 10.0.0.1 255.255.255.0
no ip proxy-arp
no ip unreachables
ip access-group FILTER_in in
!
要比较的第二个文本文件:
# filename: f_02.txt
!
interface Ethernet0/0
ip address 10.0.0.1 255.255.255.0
ip proxy-arp
no ip unreachables
!
我在 运行ning Python 3.7.6 Ubuntu 18...我有 ydiff==1.1
(github: ydiff
)
os.system()
下的 运行 似乎至少修复了差异颜色渲染...但我还没有弄清楚为什么 os.system()
修复它。
import os
TEST_04 = True
if TEST_04:
os.system("diff -u f_01.txt f_02.txt | ydiff -s")
这是 tty 设置问题之一。果然,快速查看 ydiff.py
显示它正在检查 sys.stdout.isatty()
(又名 os.isatty(2)
),这用于确定您的 stdout fd 是否通过管道传输到某个命令。然后您可以决定去除颜色格式,这就是 ydiff 对您所做的。
"diff -u f_01.txt f_02.txt | ydiff -s "
这 不是 在 os.system
调用期间通过管道传送到命令,但 它是 在任何期间subprocess
命令,因为您正在使用 stdout=PIPE
。
例如,如果您将测试脚本的输出通过管道传输到 less
,您会发现 subprocess
方法也不起作用,因为您现在已将管道添加到 stdout
你的测试因此使 ydiff.py
有一个管道到 less
。
无聊的部分结束了:阅读 ydiff.py
的选项处理显示它有一个 --color 选项,它以这种方式解析。
if (opts.color == 'always' or
(opts.color == 'auto' and sys.stdout.isatty())):
markup_to_pager(stream, opts)
else:
# pipe out stream untouched to make sure it is still a patch
byte_output = (sys.stdout.buffer if hasattr(sys.stdout, 'buffer')
else sys.stdout)
for line in stream:
byte_output.write(line)
因此,您可以将其添加到命令行以使其正常工作。
if TEST_02:
cmd_02_shell = "diff -u f_01.txt f_02.txt | ydiff -s --color='always'"
问得好,因为我喜欢 ydiff.py
的输出
此处略作修改:
不知道您是否意识到,但是 ydiff 也非常适合显示 git 差异。要在您的 repo 目录中尝试,只需执行此操作。接受一个可选文件进行比较。
$ ydiff -s [my_git_file]
如果你问我的话,非常酷。
我正在尝试构建一个 python 应用程序以在 python 中快速生成颜色并排差异。我的问题是我可以从 linux CLI 并排生成,但是无论我尝试过什么命令处理(请参阅下面的尝试),差异在 python 下都会失败。
这是 正确的行为 如果我 运行 来自 linux CLI 的差异(在 wsltty
). Note that I get the same output from PuTTY
下:
当我 运行 来自 python 脚本的差异时,这是典型的 不需要的行为 ...
问题:
- 为什么下面的 python 尝试无法生成并排差异?
- 我可以做什么(在 python 下)来尽可能地从 CLI(上面的屏幕截图)呈现输出?
下面的 python 脚本包含了我试图让 python 渲染并排差异工作的尝试...简而言之,我已经尝试了很多次Popen()
,以及 subprocess.run()
和 os.system()
...
# filename: test_ydiff.py
from subprocess import run, Popen, PIPE
import shlex, os, pydoc
TEST_01 = True
TEST_02 = True
TEST_03 = True
if TEST_01:
cmd_01_input = "diff -u f_01.txt f_02.txt"
cmd_01_output = "ydiff -s"
proc_01_input = Popen(shlex.split(cmd_01_input),
stdout=PIPE)
proc_01_output = Popen(shlex.split(cmd_01_output),
stdin=proc_01_input.stdout, stdout=PIPE)
stdout_str, stdin_str = proc_01_output.communicate()
print(stdout_str.decode('utf-8'))
if TEST_02:
cmd_02_shell = "diff -u f_01.txt f_02.txt | ydiff -s"
proc_02_shell = Popen(cmd_02_shell, shell=True, stdout=PIPE)
stdout_str, stdin_str = proc_02_shell.communicate()
print(stdout_str.decode('utf-8'))
if TEST_03:
run("/usr/bin/diff -u ./f_01.txt ./f_02.txt|/home/mpennington/venv/py37_u18/bin/ydiff -s")
要比较的第一个文本文件:
# filename: f_01.txt
!
interface Ethernet0/0
ip address 10.0.0.1 255.255.255.0
no ip proxy-arp
no ip unreachables
ip access-group FILTER_in in
!
要比较的第二个文本文件:
# filename: f_02.txt
!
interface Ethernet0/0
ip address 10.0.0.1 255.255.255.0
ip proxy-arp
no ip unreachables
!
我在 运行ning Python 3.7.6 Ubuntu 18...我有 ydiff==1.1
(github: ydiff
)
os.system()
下的 运行 似乎至少修复了差异颜色渲染...但我还没有弄清楚为什么 os.system()
修复它。
import os
TEST_04 = True
if TEST_04:
os.system("diff -u f_01.txt f_02.txt | ydiff -s")
这是 tty 设置问题之一。果然,快速查看 ydiff.py
显示它正在检查 sys.stdout.isatty()
(又名 os.isatty(2)
),这用于确定您的 stdout fd 是否通过管道传输到某个命令。然后您可以决定去除颜色格式,这就是 ydiff 对您所做的。
"diff -u f_01.txt f_02.txt | ydiff -s "
这 不是 在 os.system
调用期间通过管道传送到命令,但 它是 在任何期间subprocess
命令,因为您正在使用 stdout=PIPE
。
例如,如果您将测试脚本的输出通过管道传输到 less
,您会发现 subprocess
方法也不起作用,因为您现在已将管道添加到 stdout
你的测试因此使 ydiff.py
有一个管道到 less
。
无聊的部分结束了:阅读 ydiff.py
的选项处理显示它有一个 --color 选项,它以这种方式解析。
if (opts.color == 'always' or
(opts.color == 'auto' and sys.stdout.isatty())):
markup_to_pager(stream, opts)
else:
# pipe out stream untouched to make sure it is still a patch
byte_output = (sys.stdout.buffer if hasattr(sys.stdout, 'buffer')
else sys.stdout)
for line in stream:
byte_output.write(line)
因此,您可以将其添加到命令行以使其正常工作。
if TEST_02:
cmd_02_shell = "diff -u f_01.txt f_02.txt | ydiff -s --color='always'"
问得好,因为我喜欢 ydiff.py
的输出此处略作修改:
不知道您是否意识到,但是 ydiff 也非常适合显示 git 差异。要在您的 repo 目录中尝试,只需执行此操作。接受一个可选文件进行比较。
$ ydiff -s [my_git_file]
如果你问我的话,非常酷。