在python子进程popen中格式化命令 [英] Formatting a command in python subprocess popen

查看:48
本文介绍了在python子进程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'

谷歌搜索错误表明当为未定义的键请求值时会发生这种情况,但我不明白这里的上下文

解决方案

  1. 最简单的方法,特别是如果您希望保留输出重定向的内容,是使用 subprocessshell=True - 那么你只需要转义 Python 特殊字符.该行作为一个整体将被默认 shell 解释.

    • 警告:不要在未首先对其进行消毒的情况下将其用于不受信任的输入!
  2. 或者,您可以将命令行替换为 argv 类型的序列,并将其提供给 subprocess.然后,您需要提供程序会看到的内容:

    • 删除所有 shell 级转义
    • 删除输出重定向的内容,而是自己进行重定向

关于具体问题:

  • 你没有对字符串中的 Python 特殊字符进行转义,所以 \t\n 成为文字制表符和换行符(尝试 print awk_command)
  • 使用 shlex.splitshell=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

解决方案

  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. 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. 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)
  • 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).

    • 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆