lo abre, calcula los valores mínimo, máximo y medio de los elementos de la línea y los escribe en el archivo de salida:
Si el archivo de entrada tiene más de un línea, como el siguiente:
el archivo de salida tendrá el mismo número de líneas, cada una de las cuales con el valor mínimo, máximo y medio de la correspondiente línea del archivo de entrada:
El script acepta el argumento opcional desde la línea de comandos, que representa el nombre del directorio en el cual guardará el archivo. Si no se le pasa este argumento, los dos archivos de salida se guardarán en un directorio llamado out:
En cambio, si pasamos desde la línea de comandos un argumento, este se utilizará como en el directorio de salida:
Si el directorio de salida existe, el script lo señala con un primer mensaje en pantalla y después continúa su ejecución:
Ahora que ya sabemos qué hace el script, trataremos de entender el significado de su código. El primer paso consiste en descubrir cómo lee los argumentos pasados desde la línea de comandos.
Paso de los argumentos desde la línea de comandos
Los argumentos pasados al programa desde la línea de comandos son memorizados por Python en una lista accesible mediante el módulo sys. Esta lista se denomina sys.argv y contiene, como primer elemento, el nombre del archivo y como restantes, los otros argumentos pasados desde la línea de comandos:
NOTA
El nombre argv significa argument vector y procede de C, donde se utiliza habitualmente para indicar el parámetro al cual deben asignarse los argumentos pasados desde la línea de comandos:
Los elementos de sys.argv son cadenas, por lo que es preciso convertirlos en el tipo correcto para poder utilizarlos de manera apropiada:
En nuestro script el nombre del directorio de salida se asigna con la instrucción:
La expresión condicional a la derecha del signo igual valora como expresión de prueba la fragmentación de sys.argv, precisamente sys.argv[1:]. Como ya hemos dicho, ante una lista mylist, la fragmentación mylist[i:j] devuelve una lista de los elementos de mylist a partir de aquel con el índice i y hasta aquel con el índice j exclusive. Si el índice j se omite, la fragmentación devuelve todos los elementos a partir de aquel con el índice i, hasta el final de la lista. Consideremos, por ejemplo, el siguiente script:
y lo ejecutamos dos veces. La primera vez no le pasamos ningún argumento desde la línea de comandos, mientras que la segunda le pasamos tres argumentos:
Volviendo a nuestro código, cuando pasamos a python solo el nombre del archivo, la lista sys.argv[1:] queda vacía. Puesto que una lista vacía se valora como False en una prueba de verdad:
la expresión condicional sys.argv[1] ifsys.argv[1:] else 'out' devuelve 'out' y, por tanto, se asigna out_dir_name = 'out'.
En cambio, si además del nombre del archivo se pasa un argumento posterior, entonces sys.argv[1:] no queda vacía y se valora como True. En este caso, por tanto, se asigna out_dir_name = sys.argv[1].
Si quisiéramos realizar el análisis de los argumentos pasados desde la línea de comandos, de manera que aparezcan una ayuda y un mensaje de uso, o bien que se gestionen los errores si se pasan al programa argumentos no válidos, en tal caso será necesario utilizar el módulo argparse de la librería estándar. Dicho módulo realiza el análisis de los elementos de sys.argv, genera automáticamente los mensajes de uso y también gestiona los errores. Veremos un ejemplo de uso de este módulo en el Capítulo 2.
La interacción con el sistema operativo
Nuestro script debe ser capaz de interactuar con el sistema operativo, tanto para crear el directorio de salida, en el caso en que no exista, como para buscar los archivos con extensión .data dentro del directorio de trabajo. Como ya hemos mencionado anteriormente, es el módulo os quien proporciona esta interacción. De hecho, en el script hemos utilizado la función os.mkdir() para crear los directorios de salida:
Si el directorio existe, os.mkdir() genera una excepción de tipo FileExistsError:
Por esta razón, la instrucción que contiene os.mkdir() ha sido insertada dentro de la instrucción try. Así, si el directorio ya existe, se detecta una excepción y el flujo de ejecución pasa directamente a la cláusula except, saltando la print() inmediatamente después de os.mkdir(). A este punto, la suite de la except muestra un mensaje avisando de que el directorio ya existe, y la ejecución pasa a la instrucción for.
La función os.listdir() llamada sin argumentos devuelve una lista de los nombres de archivo y directorios incluidos dentro del directorio actual:
El bucle for itera sobre la lista devuelta por os.listdir() y ejecuta acciones solo si el nombre del archivo acaba en .data. Los archivos con la extensión .data son los siguientes:
Para cada uno de ellos debe crearse un archivo de salida cuyo nombre es otorgado por:
La función os.path.join() une una o más rutas, usando como separador el propio del sistema operativo en uso, por tanto, una barra inclinada en los sistemas Unix-like: