在 python 子进程 popen 中格式化命令
Formatting a command in python subprocess popen
我正在尝试格式化以下 awk 命令
awk -v OFS="\t" '{printf "chr%s\t%s\t%s\n", , -1, }' file1.txt > file2.txt
用于 python 子进程 popen。但是我很难格式化它。我尝试过类似答案中建议的解决方案,但其中 none 有效。我也尝试过使用原始字符串文字。我也不想使用 shell=True 因为不推荐使用
根据评论编辑:
我尝试的命令是
awk_command = """awk -v OFS="\t" '{printf "chr%s\t%s\t%s\n", , -1, }' file1.txt > file2.txt"""
command_execute = Popen(shlex.split(awk_command))
但是我在执行此操作时收到以下错误
KeyError: 'printf "chr%s\t%s\t%s\n", , -1, '
谷歌搜索错误表明当为未定义的键请求值时会发生这种情况,但我在这里不理解它的上下文
最简单的方法,特别是如果你想保留输出重定向的东西,就是使用 subprocess
和 shell=True
- 那么你只需要转义 Python 特殊的角色。该行作为一个整体,将被默认解释为 shell.
- 警告:请勿在未先清理的情况下将其用于不受信任的输入!
或者,您可以将命令行替换为 argv
类型的序列,并将其提供给 subprocess
。然后,您需要提供程序会看到的内容:
- 删除所有shell级转义
- 删除输出重定向内容并改为自己进行重定向
关于具体问题:
- 你没有转义字符串中的 Python 特殊字符,所以
\t
和 \n
变成了文字制表符和换行符(尝试 print awk_command
)
使用 shlex.split
与 shell=True
没有什么不同 - 增加了不可靠性,因为它不能保证是否会像 shell 一样解析字符串每种情况(更不用说缺少 shell 所做的转换)。
具体来说,不知道也不关心重定向部分的特殊含义:
>>> awk_command = """awk -v OFS="\t" '{printf "chr%s\t%s\t%s\n", , - 1, }' file1.txt > file2.txt"""
>>> shlex.split(awk_command)
['awk','-v','OFS=\t','{printf "chr%s\t%s\t%s\n", , -1, }','file1.txt','>','file2.txt']
因此,如果您想使用 shell=False
,请自行构建参数列表。
>
是 shell 重定向运算符。要在 Python 中实现它,请使用 stdout
参数:
#!/usr/bin/env python
import shlex
import subprocess
cmd = r"""awk -v OFS="\t" '{printf "chr%s\t%s\t%s\n", , -1, }'"""
with open('file2.txt', 'wb', 0) as output_file:
subprocess.check_call(shlex.split(cmd) + ["file1.txt"], stdout=output_file)
为避免启动单独的进程,您可以在纯 Python.
中实现此特定的 awk
命令
我正在尝试格式化以下 awk 命令
awk -v OFS="\t" '{printf "chr%s\t%s\t%s\n", , -1, }' file1.txt > file2.txt
用于 python 子进程 popen。但是我很难格式化它。我尝试过类似答案中建议的解决方案,但其中 none 有效。我也尝试过使用原始字符串文字。我也不想使用 shell=True 因为不推荐使用
根据评论编辑: 我尝试的命令是
awk_command = """awk -v OFS="\t" '{printf "chr%s\t%s\t%s\n", , -1, }' file1.txt > file2.txt"""
command_execute = Popen(shlex.split(awk_command))
但是我在执行此操作时收到以下错误
KeyError: 'printf "chr%s\t%s\t%s\n", , -1, '
谷歌搜索错误表明当为未定义的键请求值时会发生这种情况,但我在这里不理解它的上下文
最简单的方法,特别是如果你想保留输出重定向的东西,就是使用
subprocess
和shell=True
- 那么你只需要转义 Python 特殊的角色。该行作为一个整体,将被默认解释为 shell.- 警告:请勿在未先清理的情况下将其用于不受信任的输入!
或者,您可以将命令行替换为
argv
类型的序列,并将其提供给subprocess
。然后,您需要提供程序会看到的内容:- 删除所有shell级转义
- 删除输出重定向内容并改为自己进行重定向
关于具体问题:
- 你没有转义字符串中的 Python 特殊字符,所以
\t
和\n
变成了文字制表符和换行符(尝试print awk_command
) 使用
shlex.split
与shell=True
没有什么不同 - 增加了不可靠性,因为它不能保证是否会像 shell 一样解析字符串每种情况(更不用说缺少 shell 所做的转换)。具体来说,不知道也不关心重定向部分的特殊含义:
>>> awk_command = """awk -v OFS="\t" '{printf "chr%s\t%s\t%s\n", , - 1, }' file1.txt > file2.txt""" >>> shlex.split(awk_command) ['awk','-v','OFS=\t','{printf "chr%s\t%s\t%s\n", , -1, }','file1.txt','>','file2.txt']
因此,如果您想使用 shell=False
,请自行构建参数列表。
>
是 shell 重定向运算符。要在 Python 中实现它,请使用 stdout
参数:
#!/usr/bin/env python
import shlex
import subprocess
cmd = r"""awk -v OFS="\t" '{printf "chr%s\t%s\t%s\n", , -1, }'"""
with open('file2.txt', 'wb', 0) as output_file:
subprocess.check_call(shlex.split(cmd) + ["file1.txt"], stdout=output_file)
为避免启动单独的进程,您可以在纯 Python.
中实现此特定的awk
命令