在python子进程popen中格式化命令 [英] Formatting a command in python subprocess popen
问题描述
我正在尝试格式化以下 awk 命令
awk -v OFS="\t" '{printf "chr%s\t%s\t%s\n", $1, $2-1, $2}' file1.txt >文件2.txt
用于 python 子进程 popen.但是我很难格式化它.我尝试过类似答案中建议的解决方案,但没有一个奏效.我也尝试过使用原始字符串文字.我也不想使用 shell=True 因为不推荐使用
根据评论我试过的命令是
awk_command = """awk -v OFS="\t" '{printf "chr%s\t%s\t%s\n", $1, $2-1, $2}' file1.txt > file2.txt"""command_execute = Popen(shlex.split(awk_command))
但是我在执行此操作时收到以下错误
KeyError: 'printf "chr%s\t%s\t%s\n", $1, $2-1, $2'
谷歌搜索错误表明当为未定义的键请求值时会发生这种情况,但我不明白这里的上下文
最简单的方法,特别是如果您希望保留输出重定向的内容,是使用
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, $2-1, $2}' file1.txt >file2.txt""">>>shlex.split(awk_command)['awk','-v','OFS=\\t','{printf "chr%s\\t%s\\t%s\\n", $1, $2-1, $2}','file1.txt','>','file2.txt']
因此,如果您希望使用 shell=False
,请自行构建参数列表.
I am trying to format the following awk command
awk -v OFS="\t" '{printf "chr%s\t%s\t%s\n", $1, $2-1, $2}' file1.txt > file2.txt
for use in python subprocess popen. However i am having a hard time formatting it. I have tried solutions suggested in similar answers but none of them worked. I have also tried using raw string literals. Also i would not like to use shell=True as this is not recommended
Edit according to comment: The command i tried was
awk_command = """awk -v OFS="\t" '{printf "chr%s\t%s\t%s\n", $1, $2-1, $2}' file1.txt > file2.txt"""
command_execute = Popen(shlex.split(awk_command))
However i get the following error upon executing this
KeyError: 'printf "chr%s\t%s\t%s\n", $1, $2-1, $2'
googling the error suggests this happens when a value is requested for an undefined key but i do not understand its context here
The simplest method, especially if you wish to keep the output redirection stuff, is to use
subprocess
withshell=True
- then you only need to escape Python special characters. The line, as a whole, will be interpreted by the default shell.- WARNING: do not use this with untrusted input without sanitizing it first!
Alternatively, you can replace the command line with an
argv
-type sequence and feed that tosubprocess
instead. Then, you need to provide stuff as the program would see it:- remove all the shell-level escaping
- remove the output redirection stuff and do the redirection yourself instead
Regarding the specific problems:
- you didn't escape Python special characters in the string so
\t
and\n
became the literal tab and newline (try toprint awk_command
) using
shlex.split
is nothing different fromshell=True
- with an added unreliability since it cannot guarantee if would parse the string the same way your shell would in every case (not to mention the lack of transmutations the shell makes).Specifically, it doesn't know or care about the special meaning of the redirection part:
>>> awk_command = """awk -v OFS="\\t" '{printf "chr%s\\t%s\\t%s\\n", $1, $2- 1, $2}' file1.txt > file2.txt""" >>> shlex.split(awk_command) ['awk','-v','OFS=\\t','{printf "chr%s\\t%s\\t%s\\n", $1, $2-1, $2}','file1.txt','>','file2.txt']
So, if you wish to use shell=False
, do construct the argument list yourself.
这篇关于在python子进程popen中格式化命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!