Saltar al contenido principal
LibreTexts Español

2.7: Interfaz de línea de comandos

  • Page ID
    55098
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    Si bien Python es un gran lenguaje para la programación independiente, también es un lenguaje de primera clase para interactuar con la línea de comandos Unix/Linux. Este capítulo explora algunos de esos conceptos, permitiéndonos usar Python como “pegamento” para conectar otros poderosos conceptos de línea de comandos.

    La entrada estándar es un manejador de archivo

    En capítulos anteriores, vimos que las utilidades simples de Unix/Linux como grep y sort se pueden encadenar para una variedad de tareas de manipulación de datos.

    II.7_1_py_57_sort_blast_stdin

    El comando anterior utiliza grep para hacer coincidir las líneas del archivo pz_stats.table con el patrón _L, que se imprimen a la salida estándar. Usando la redirección |, enviamos esta salida para ordenar en su entrada estándar y ordenar las líneas de la segunda columna en orden numérico general, antes de canalizar esta salida a menos -S.

    II.7_2_PY_58_Sort_blast_stdin_out

    Nuevamente, sort y less no están leyendo su entrada de un archivo, sino de flujos de entrada estándar. Del mismo modo, no están escribiendo su salida en un archivo, sino simplemente imprimiendo a las secuencias de salida estándar. A menudo es útil diseñar nuestras propias pequeñas utilidades como programas Python que operan de la misma manera.

    La analogía de “file handle as a pipe” que hemos estado usando nos servirá bien a la hora de escribir programas que leen entrada de entrada estándar. El manejador de archivo asociado con la entrada estándar es fácil de usar en Python. Solo tenemos que importar el módulo sys, y luego sys.stdin es una variable que hace referencia al manejador de archivo de solo lectura que funciona igual que cualquier otra. Ni siquiera tenemos que usar io.open (). Aquí hay un programa que imprime cada línea que pasa a él en la entrada estándar.

    II.7_3_py_59_stdin_ex

    En este caso, estamos usando sys.stdin de manera muy parecida a los manejadores de archivos de solo lectura que vimos en ejemplos anteriores. Podemos probar nuestro programa en un archivo simple que contiene algunos ID de genes:

    II.7_4_py_60_stdin_ex_out

    Pero si intentamos ejecutar nuestro programa sin darle ninguna entrada en el flujo de entrada estándar, se sentará y esperará datos que nunca llegarán.

    II.7_5_py_61_stdin_ex_esperando

    Para matar el programa, podemos usar el Control-C habitual. La razón de este comportamiento es que el flujo de entrada estándar se puede utilizar para la entrada desde el estándar de otro programa (como deseamos hacer), o puede usarse para construir programas interactivos. Para ver esto, podemos ejecutar el mismo programa, excepto que esta vez vamos a escribir alguna entrada usando el teclado, y cuando hayamos terminado enviaremos el código de control Control-D, que es una forma de decirle a Python que hemos terminado de enviar entrada.

    II.7_6_py_62_stdin_ex_waiting2

    Esto sugiere algunas posibilidades interesantes para programas interactivos, [1] pero en este caso probablemente sería confuso para alguien que quiera utilizar nuestro programa canalizando datos a él. Afortunadamente, sys.stdin tiene un método llamado .isatty () que devuelve True si no hay datos presentes en el flujo de entrada cuando se llama. (TTY es la abreviatura de “TeleTypeWriter”, un nombre común para un dispositivo de entrada conectado al teclado de décadas pasadas). Entonces, podemos modificar nuestro programa con bastante facilidad para que salga con algún texto de uso útil si detecta que no hay datos presentes en la entrada estándar.

    II.7_7_py_63_stdin_ex_waiting3

    Casi siempre es una buena idea que un programa verifique si se está llamando correctamente, y que dé alguna información útil de uso si no. También es común incluir, en comentarios cercanos a la parte superior del programa, información de autoría como fecha de última actualización e información de contacto. También puede necesitar o querer incluir algún texto de derechos de autor y licencia, ya sea de su elección o el de su institución.

    Tenga en cuenta que no hemos llamado a .close () en el controlador de archivo de entrada estándar. Aunque Python no se quejará si lo haces, no es obligatorio, ya que la entrada estándar es un tipo especial de manejador de archivos que el sistema operativo maneja automáticamente.

    Salida estándar como manejador de archivo

    Cualquier cosa impresa por un programa Python se imprime en el flujo de salida estándar, por lo que esta salida también se puede enviar a otros programas para su procesamiento.

    II.7_8_py_64_stdout_sort

    Sin embargo, el módulo sys también proporciona acceso al controlador de archivo de salida estándar, sys.stdout. Al igual que otros manejadores de archivos orientados a la salida, podemos llamar a .write () en este manejador de archivo para imprimir. La principal diferencia entre este método y llamar a print () es que mientras print () por defecto agrega un carácter de nueva línea “\ n” sys.stdout.write () no lo hace. [2] Esta característica puede ser particularmente útil cuando deseamos imprimir una tabla de manera elemento por elemento porque los datos no se almacenan en cadenas que representan filas individuales.

    II.7_9_py_65_stdout_table

    Salida de lo anterior:

    II.7_10_py_66_stdout_table_out

    Si bien print () es una forma sencilla de imprimir una línea de texto, sys.stdout.write () le brinda más control sobre el formato de la salida impresa. Al igual que con sys.stdin, no es necesario llamar a .close () en el controlador de archivo. A diferencia de otros manejadores de archivos orientados a la salida, los datos se descargan regularmente de la tubería (ya sea para imprimir o para la entrada estándar de otro programa).

    Parámetros de Línea de Comandos

    Hasta ahora, a pesar de que hemos estado ejecutando nuestros programas desde la línea de comandos, ninguno de nuestros programas Python ha aceptado parámetros de entrada. Considere el ejemplo del capítulo 18, “Funciones de Python”, donde calculamos el contenido de GC para cada secuencia en un archivo. En lugar de codificar el nombre del archivo en la llamada io.open (), sería preferible proporcionar el nombre del archivo con el que trabajar en la línea de comandos, como en. /ids_seqs_gcs.py ids_seqs.txt.

    El módulo sys vuelve a venir al rescate. Después de importar sys, la variable sys.argv hace referencia a una lista de cadenas que contienen, comenzando en el índice 0, el nombre del script en sí, luego cada parámetro. Debido a que sys.argv es siempre una lista de cadenas, si queremos introducir un argumento float o integer, necesitaremos convertir el parámetro apropiado usando int () o float () antes de usarlo.

    II.7_11_PY_67_Params_ex

    Este código también determina si el número esperado de parámetros ha sido dado por el usuario mirando len (sys.argv), saliendo si este no es el caso.

    II.7_12_PY_68_Params_ex_out1

    Al igual que con otros programas ejecutados en la línea de comandos, si queremos enviar un solo parámetro que contenga espacios, necesitamos envolverlo en comillas simples o dobles.

    II.7_13_PY_69_PARAMS_EX_OUT2

    Aunque no lo cubriremos aquí, el módulo argparse hace que escribir scripts que requieran parámetros de entrada de diferentes tipos sea relativamente fácil. El módulo argparse también automatiza la impresión y formateo de la información de ayuda a la que pueden acceder los usuarios que ejecutan el programa con un indicador -h o —help. Una variedad de tutoriales para argparse se pueden encontrar en línea. (También hay un optparse de módulo más simple, pero menos funcional).

    Ejecución de Comandos de Shell dentro de Python

    A veces es útil ejecutar otros programas desde dentro de nuestros propios programas. Esto podría deberse a que queremos ejecutar una serie de comandos generados algorítmicamente (por ejemplo, tal vez queremos ejecutar un programa de ensamblaje de genoma en una variedad de archivos en secuencia), o tal vez queremos que la salida de un programa se ejecute en la línea de comandos.

    Considere la tarea de línea de comandos de enumerar todos los archivos en el directorio actual que coincidan con el cluster de patrón*.fasta. Para ello podemos usar ls -1 cluster*.fasta, donde -1 le dice a ls que imprima su salida como una sola columna de nombres de archivo, y cluster*.fasta coincide con todos los nombres de archivo que coincidan con el patrón deseado (como cluster_ab.fasta, Cluster_ac.fasta, cluster_ag.fasta y cluster_d.fasta.).

    II.7_14_py_70_ls_fasta

    Hay algunas formas de obtener esta información en un programa Python, pero una de las más fáciles es ejecutar el comando ls -1 cluster*.fasta desde dentro de nuestro programa, capturando el resultado como una cadena. [3] El módulo de subproceso nos permite hacer exactamente esto mediante el uso de la función subprocess.check_output (). Esta función toma una serie de parámetros potenciales, pero la ejecutaremos con solo dos: (1) el comando que deseamos ejecutar (como una cadena) y (2) shell = True, lo que indica que el intérprete de Python debería ejecutar el comando como si lo hubiéramos ejecutado en la línea de comandos.

    El resultado de la llamada a la función es una sola cadena que contiene cualquiera que sea el comando impreso a la salida estándar. Debido a que es una sola cadena, si queremos que se represente como una lista de líneas, primero necesitamos .strip () de cualquier carácter de nueva línea al final, y luego dividirlo en los\ n caracteres que separan las líneas.

    II.7_15_PY_71_Subprocess_LS

    Al ejecutar el programa, vemos que el resultado es una lista de cadenas, una por archivo:

    II.7_16_PY_72_subprocess_list_out

    Con esta lista de nombres de archivo en la mano, podríamos desear ejecutar una serie de ensamblajes con el programa RunAssembly (producido por 454 Life Sciences para ensamblar secuencias de transcripción). Este programa requiere un parámetro -o para especificar dónde deben escribirse las salidas así como una entrada de nombre de archivo; las generamos con operaciones de cadena para “construir” un comando a ejecutar. Una vez que estemos satisfechos con los comandos, podemos descomentar la llamada real a subprocess.check_output ().

    II.7_17_PY_72_2_Subprocess_Run_Asambleas

    Esta versión del programa informa de los comandos que se ejecutarán. [4]

    II.7_18_PY_72_3_RunAssembly_out

    Mientras un comando se ejecuta a través de la función subprocess.check_output () de esta manera, el programa esperará antes de continuar a la siguiente línea (aunque probablemente solo notará si el comando tarda mucho en ejecutarse). Si el comando se bloquea o se mata, el programa Python también se bloqueará con un llamado ProcessError (¡generalmente es algo bueno!).

    Otras funciones del módulo de subprocesos permiten ejecutar comandos en segundo plano, por lo que el script no espera a que se completen antes de continuar en su propia ejecución, y trabajar con múltiples procesos de este tipo mientras se comunica con ellos. Otros módulos de Python incluso permiten un trabajo avanzado con ejecución paralela y subprocesos, aunque estos temas están más allá del alcance de este capítulo.

    ¡No olvides que eres el responsable de la ejecución de tus programas! Si escribes un programa que ejecuta muchos otros programas, puedes utilizar rápidamente más recursos computacionales de los que crees. Si estás trabajando en un sistema con el que no te importa tomar algunos riesgos, podrías intentar ejecutar el siguiente programa, que ejecuta una copia de sí mismo (que a su vez ejecuta una copia de sí mismo, que a su vez ejecuta una copia de sí mismo, y una y otra vez):

    II.7_19_py_73_subprocess_calls_itself

    Ejercicios

    1. En el ejemplo de impresión de tablas se utilizó sys.stdout para imprimir muy bien una mesa en orden de columna mayor. Escribe una función llamada print_row_major () que imprima una tabla almacenada en orden fila-major, por lo que una llamada como print_row_major ([["A”, “B"], ["C”, “D"], ["E”, “F"]]) da como resultado la salida con el siguiente aspecto:
      alt
    2. Escribe un programa llamado stdin_eval_mean.py que lee un archivo en el formato pz_blastx_yeast_top1.txt en sys.stdin, calcula la media de la columna E -value (columna 11, con valores como 1e-32), e imprime la media a salida estándar. Si no hay datos en la entrada estándar, el programa debe producir un mensaje de “uso”.

      A continuación, intente ejecutar el programa con cat pz_blastx_yeast_top1.txt |. /stdin_eval_mean.py. Además, intente prefiltrar las líneas antes del cálculo con algo como cat pz_blastx_yeast_top1.txt | grep '_L' |. /stdin_eval_mean.py.

      Ahora copia este programa a uno llamado stdin_eval_sd.py que lee en pz_blastx_yeast_top1.txt en sys.stdin y calcula e imprime la desviación estándar de los valores E. Nuevamente, intente ejecutar el programa con y sin prefiltrado con grep. (En este punto deberías sentirte cómodo escribiendo las funciones mean () y sd () que toman listas de flotadores y devuelven respuestas. Su función sd () bien podría llamar a la función mean ().)

    3. Modifique el programa stdin_eval_mean.py anterior (llame a la nueva versión stdin_eval_mean_threshold.py) para aceptar un umbral superior de valor E como primer parámetro. Así cat pz_blastx_yeast_top1.txt |. /stdin_eval_mean.py 1e-6 debe calcular e imprimir la media de la columna E -value, pero sólo para aquellas líneas cuyo valor E sea menor que 1e-6. (Deberá usar sys.argv y asegurarse de convertir la entrada en ella en un flotador).

      Su programa debe imprimir información de uso y salir si no hay datos proporcionados en la entrada estándar, o si no hay ningún argumento de umbral.


    1. Intenta usar una línea de código como value = input (“¿Cuál es tu nombre? “) seguido de print (valor). Tenga en cuenta que cuando ejecute el programa y se le solicite, deberá incluir comillas al escribir su nombre (por ejemplo, “Shawn”).
    2. En Python 3.0 y superiores, la función print () también puede tomar algunos parámetros para especificar si el “\ n” debe imprimirse o no, o incluso reemplazarse por algún otro carácter.
    3. Un método alternativo para obtener una lista de archivos es usar el módulo os y la función os.listdir (), que devolverá una lista de nombres de archivo. Para enumerar y trabajar con nombres de archivo y rutas, se prefieren las funciones en el módulo os, ya que funcionarán ya sea que el programa se ejecute en un sistema Windows o en un sistema similar a UNIX. Para ejecutar comandos shell de manera más general, el módulo de subprocesos es útil. Aquí estamos ilustrando que en la línea de comandos Unix/Linux, puede hacer ambos trabajos llamando a utilidades del sistema.
    4. Aquí estamos dividiendo los nombres de archivo en una lista de [nombre, extensión] con nombrearchivo.split (“.”) . Este método no funcionará si hay múltiples. s en el expediente. Una alternativa más robusta se encuentra en el módulo os: os.path.splitext (“this.file.txt”) devolvería ["this.file”, “txt"].

    This page titled 2.7: Interfaz de línea de comandos is shared under a CC BY-NC-SA license and was authored, remixed, and/or curated by Shawn T. O’Neil (OSU Press) .