Formateo de un comando en popen subproceso python

Estoy tratando de formatear el siguiente comando awk

awk -v OFS="\t" '{printf "chr%s\t%s\t%s\n", $1, $2-1, $2}' file1.txt > file2.txt 

para uso en python subprocess popen. Sin embargo estoy teniendo dificultades para formatearlo. He intentado soluciones sugeridas en respuestas similares pero ninguna de ellas funcionó. También he intentado usar literales de cadena en bruto. Además, no me gustaría usar shell = True, ya que no se recomienda

Editar de acuerdo con el comentario: El comando que probé fue

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

Sin embargo me sale el siguiente error al ejecutar este

 KeyError: 'printf "chr%s\t%s\t%s\n", $1, $2-1, $2' 

buscar en Google el error sugiere que esto suceda cuando se solicita un valor para una clave no definida pero no entiendo su contexto aquí

  1. El método más simple, especialmente si desea mantener las cosas de redireccionamiento de salida, es usar el subprocess con shell=True – entonces solo necesita escapar de los caracteres especiales de Python. La línea, en su totalidad, será interpretada por el shell predeterminado.

    • ADVERTENCIA: ¡no use esto con una entrada no confiable sin desinfectarla primero!
  2. Alternativamente, puede reemplazar la línea de comando con una secuencia de tipo argv y enviarla al subprocess . Entonces, necesitas proporcionar cosas como el progtwig lo vería:

    • eliminar todo el nivel de shell de escape
    • elimine las cosas de redirección de salida y realice la redirección usted mismo en su lugar

Respecto a los problemas específicos:

  • no escapaste de los caracteres especiales de Python en la cadena, por lo que \t y \n convirtieron en la pestaña literal y la nueva línea (intenta print awk_command )
  • el uso de shlex.split no es diferente de shell=True – con una falta de fiabilidad agregada, ya que no puede garantizar si se analizaría la cadena de la misma manera que lo haría su shell en todos los casos (sin mencionar la falta de transmutaciones que hace la shell).

    • Específicamente, no sabe ni se preocupa por el significado especial de la parte de redirección:

       >>> 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'] 

Por lo tanto, si desea usar shell=False , construya la lista de argumentos usted mismo.

> es el operador de redirección de shell. Para implementarlo en Python, use el parámetro 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) 

Para evitar iniciar un proceso separado, puede implementar este comando awk en particular en Python puro.