简体   繁体   English

在python子进程popen中格式化命令

[英]Formatting a command in python subprocess popen

I am trying to format the following awk command 我正在尝试格式化以下awk命令

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. 用于python子进程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 我也不想使用shell = True,因为这是不推荐的

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 谷歌搜索错误表明,当为一个未定义的键请求一个值,但我不了解其上下文时,会发生这种情况

> is the shell redirection operator. >是Shell重定向运算符。 To implement it in Python, use stdout parameter: 要在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, $2-1, $2}'"""
with open('file2.txt', 'wb', 0) as output_file:
    subprocess.check_call(shlex.split(cmd) + ["file1.txt"], stdout=output_file)

To avoid starting a separate process, you could implement this particular awk command in pure Python. 为了避免启动单独的过程,您可以在纯Python中实现此特定的awk命令。

  1. The simplest method, especially if you wish to keep the output redirection stuff, is to use subprocess with shell=True - then you only need to escape Python special characters. 最简单的方法(尤其是如果您希望保留输出重定向的东西)是使用带有shell=True subprocess -那么您只需要转义Python特殊字符。 The line, as a whole, will be interpreted by the default shell. 整体而言,该行将由默认外壳程序解释。

    • WARNING: do not use this with untrusted input without sanitizing it first! 警告:请勿在不先消毒的情况下将其用于不受信任的输入!
  2. Alternatively, you can replace the command line with an argv -type sequence and feed that to subprocess instead. 或者,您可以将命令行替换为argv -type序列,然后将其提供给subprocess 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 to print awk_command ) 您没有在字符串中转义Python特殊字符,因此\\t\\n成为了文字标签和换行符(尝试print awk_command
  • using shlex.split is nothing different from shell=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). 使用shlex.splitshell=True没什么不同-额外增加了可靠性,因为它不能保证在每种情况下是否都可以以与shell相同的方式解析字符串(更不用说shell缺少转换了)。

    • 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. 因此,如果您希望使用shell=False ,请自己构造参数列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM