Python se instala por defecto en la mayoría de las distribuciones de Linux. En Mac y Windows debemos instalarlo manualmente.
Es integrable con otros lenguajes de programación.
Documentación de todos los modulos de la librería estandar: https://docs.python.org/2/library/
Cuando vimos unit testing usamos la variable __name__
if __name__ == “__main__”:
pass
Solo se ejutará si se encuentra en el módulo principal
os
: provee funcionalidades para utilizar herramientas provistas por el sistema operativo.os.path
: provee: funcionalidades para manipular nombres de archivos y directorios.sys
: provee acceso a variables provistas por el intérprete.io
: provee herramientas para trabajar con streams.help(os.getcwd)
os.getcwd()
help(os.listdir)
os.listdir(".")
help(os.chdir)
print os.getcwd()
os.chdir("..")
print os.getcwd()
help(os.link)
help(os.mkdir)
help(os.remove)
help(os.unlink)
Implementar un script que liste por pantalla, en orden alfabético, el contenido del directorio donde se ejecuta.
import os
def listar_contenido_carpeta_usuario():
for archivo in os.listdir('.'):
print(archivo)
if __name__ == "__main__":
listar_contenido_carpeta_usuario()
help(os.path.dirname)
os.path.dirname("/Users/miguelalfaro/Desktop/Curso/CursoPython")
help(os.path.exists)
print os.path.exists("/Users/miguelalfaro/Desktop/Curso")
print os.path.exists("/Users/miguelalfaro/Desktop/Fotos")
help(os.path.getsize)
print os.getcwd()
os.path.getsize("Notebooks/Clase 6.ipynb")
help(os.path.isfile)
help(os.path.isdir)
os.path.isfile("Notebooks/Clase 6.ipynb")
os.path.isdir("Notebooks/Clase 6.ipynb")
os.path.isfile("Notebooks")
os.path.isdir("Notebooks")
help(os.path.join)
help(os.path.split)
os.path.join("/Users/miguelalfaro/Desktop", "Fotos")
os.path.split("/Users/miguelalfaro/Desktop/Curso")
Implementar un script que imprima en pantalla la cantidad de directorios existentes en el directorio donde se encuentra el script
#Solucion 6.2
import os
def cantidad_de_directorios():
cant = 0
for directorio in os.listdir('.'):
if os.path.isdir(directorio):
cant += 1
return cant
if __name__ == '__main__':
print cantidad_de_directorios()
Implementar un script que imprima en pantalla el nombre del archivo más pesado del directorio temporal.
import os
def archivo_mas_pesado():
max_tam = 0
archivo_max_tam = ""
for archivo in os.listdir('.'):
if not os.path.isfile(archivo):
continue
tam = os.path.getsize(archivo)
if tam > max_tam:
max_tam = tam
archivo_max_tam = archivo
return archivo_max_tam,tam
if __name__ == '__main__':
print archivo_mas_pesado()
import sys
help(sys.argv)
help(sys.getdefaultencoding)
help(sys.getrefcount)
Implementar un script que reciba por parámetro una cantidad n de cadenas y que cree una carpeta con el nombre de cada una en el directorio temporal del usuario.
import os
def crear_carpetas(nombres_carpetas):
for nombre_carpeta in nombres_carpetas:
os.mkdir(nombre_carpeta)
if __name__ == "__main__":
crear_carpetas(["directorio1", "directorio2"])
Recordemos:
>>> 'El cuadrado de {0} es {1}.'.format(str(4), str(4**2))
'El cuadrado de 4 es 16.'
>>> "Mañana será {dia} de {mes}".format(dia=str(3), mes="agosto")
'Mañana será 3 de agosto'
>>> 'El número complejo es {z.real} + {z.imag}i.'.format(z=3+2j)
'El número complejo es 3.0 + 2.0i.'
"{" [nombre_campo] ["!" conversión] [":" formato] "}"
Caracter | Función |
---|---|
r | repr() |
s | str() |
a | ascii() |
Resulta, entonces:
>>> "{0!s}".format(A()) == "{0}".format(str(A()))
True
Todas la opciones disponibles en la documentación oficial: https://docs.python.org/2/library/string.html#format-string-syntax
[[relleno]alineación][signo][#][0][ancho][,][.precisión][tipo]
>>> '{:*^30}'.format('centered')
'***********centered***********'
>>> "int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}".format(42)
'int: 42; hex: 2a; oct: 52; bin: 101010'
>>> for align, text in zip('<^>', ['left', 'center', 'right']): '{0:{fill}{align}16}'.format(text, fill=align, align=align)
'left<<<<<<<<<<<<'
'^^^^^center^^^^^'
'>>>>>>>>>>>right'
Función | Uso |
---|---|
.rjust(n) | Justifica a derecha n columnas |
.ljust(n) | Justifica a izquierda n columnas |
.center(n) | Centra n columnas |
>>> for i, v in enumerate(['a', 'b', 'c', 'd']): print(str(i).rjust(5)), v.rjust(5))
0a 1b 2c 3d
>>> "El cuadrado de %d es %d." % (4, 4**2)
'El cuadrado de 4 es 16.'
>>> 'Mañana será %d de %s.' % (3, "agosto")
'Mañana será 3 de agosto.'
Imprimir por pantalla una tabla de conversión de grados Celsius a Farenheit y Kelvin, sabiendo que:
°K = °C + 273,15
°F = 9/5 ∙ °C + 32
Implementar la tabla desde 0°C hasta 200°C considerando incrementos de a 20 °C.
def celsius_a_kelvin(temp_celsius):
return temp_celsius + 273.15
def celsius_a_farenheit(temp_celsius):
return temp_celsius * (9/5) + 32
def imprimir_tabla_conversion_temperaturas():
print("C".center(8), "F".center(8), "K".center(8))
for temp_c in range(0, 201, 20):
temp_f = celsius_a_farenheit(temp_c)
temp_k = celsius_a_kelvin(temp_c)
#print("{0:^8} {1:^8} {2:^8}".format(temp_c, temp_f, temp_k))
print(str(temp_c).rjust(8), str(temp_f).rjust(8), str(temp_k).rjust(8))
imprimir_tabla_conversion_temperaturas()
(' C ', ' F ', ' K ') (' 0', ' 32', ' 273.15') (' 20', ' 52', ' 293.15') (' 40', ' 72', ' 313.15') (' 60', ' 92', ' 333.15') (' 80', ' 112', ' 353.15') (' 100', ' 132', ' 373.15') (' 120', ' 152', ' 393.15') (' 140', ' 172', ' 413.15') (' 160', ' 192', ' 433.15') (' 180', ' 212', ' 453.15') (' 200', ' 232', ' 473.15')
Escribir una función que imprima por pantalla una tabla con nombre – tipo (“a” para archivos, “d” para directorios) – peso para el contenido del directorio de prueba.
Nombre Tipo Tamaño
archivo no vacio a 14
archivo vacio a 14
directorio 1 d 0
directorio 2 d 0
hola mundo.txt a 20
lorem 1.txt a 682
lorem 2.txt a 1451
lorem 3.txt a 100
import os
def obtener_tipo(nombre_archivo):
''' Devuelve 'a' en caso de que el nombre pasado por parámetro
sea un archivo, 'd' en caso de que sea un directorio.
'''
return 'a' if os.path.isfile(nombre_archivo) else 'd'
def imprimir_info_directorio_prueba():
# Cambia el directorio de trabajo.
path = os.path.join(os.getcwd(), "ejemplos/clase6", "Directorio de prueba")
os.chdir(path)
# Imprime la tabla
formato_tabla = "{0:<20} {1:<6} {2:<20}"
print(formato_tabla.format("Nombre", "Tipo", "Tamaño"))
for archivo in os.listdir(path):
print(formato_tabla.format(archivo, obtener_tipo(archivo), os.path.getsize(archivo)))
imprimir_info_directorio_prueba()
Nombre Tipo Tamaño .DS_Store a 6148 archivo no vacio a 14 archivo vacio a 14 directorio 1 d 102 directorio 2 d 102 hola mundo.txt a 20 lorem 1.txt a 682 lorem 2.txt a 1451 lorem 3.txt a 100
archivo = open(nombre_archivo, modo)
.Modo | Función |
---|---|
'r' | Sólo lectura (defecto) |
'w' | Sólo escritura |
'a' | Agregar al final |
'r+' | Lectura y escritura |
'b' | Binario |
archivo.close()
try:
fp = open(nombre_archivo)
except IOError:
# Manejar error.
pass
else:
# Procesar archivo fp.close()
Solemos usar el operador with para manejar archivos, reemplazando try / finally
:
with open(nombre_archivo) as fp:
# Código de ejecución, usando fp pass
Así nos aseguramos de cerrarlos siempre.
Usamos los métodos de cadena para ignorar el salto de línea:
Otras métodos de cadenas que pueden servir:
Implementar un programa que a partir del archivo de letra / número “tabla1.txt” del directorio “Archivos de prueba”, devolver un diccionario en donde las claves sean los valores posibles de las letras (“a”, “b”, “c”, “d”, “e”) y en donde los valores asociados del diccionario sean la suma para cada letra de los números del archivo.
import os
def crear_diccionario_valores():
# Procesa el archivo.
try:
archivo = open("tabla1.txt")
except IOError as ioe:
print("No se encuentra el archivo!")
else:
tabla = {}
for linea in archivo:
valores = linea.rstrip().split()
letra = valores[0]
numero = int(valores[1])
tabla[letra] = tabla.get(letra, 0) + numero
archivo.close()
return tabla
print(crear_diccionario_valores())
No se encuentra el archivo!
--------------------------------------------------------------------------- UnboundLocalError Traceback (most recent call last) <ipython-input-24-3ee8c8b126c5> in <module>() 20 21 ---> 22 print(crear_diccionario_valores()) <ipython-input-24-3ee8c8b126c5> in crear_diccionario_valores() 10 11 tabla = {} ---> 12 for linea in archivo: 13 valores = linea.rstrip().split() 14 letra = valores[0] UnboundLocalError: local variable 'archivo' referenced before assignment
Implementar un programa que devuelva un diccionario de configuraciones a partir del archivo de entrada “parametros.txt”
import os
def obtener_parametros():
# Procesa el archivo.
parametros = {}
with open("parametros.txt") as archivo:
for linea in archivo:
parametro = linea.split("=")
parametro = map(str.strip, parametro)
parametros[parametro[0]] = parametro[1]
return parametros
print(obtener_parametros())
{'status': 'openvpn-status.log', 'persist-key': '1', 'comp-lzo': '1', 'dh': 'dh1024.pem', 'proto': 'udp', 'ca': 'ca.crt', 'mute': '20', 'server-bridge': '10.8.0.4 255.255.255.0 10.8.0.50 10.8.0.100', 'dev': 'tap0', 'persist-tun': '32', 'cert': 'server.crt', 'verb': '3', 'key': 'server.key', 'ifconfig-pool-persist': 'ipp.txt', 'max-clients': '100', 'port': '1194', 'keepalive': '10 120'}
Para abrir un archivo para escritura se debe hacer de alguno de los siguientes modos:
Modo | Función |
---|---|
'w' | Sólo escritura |
'a' | Agregar al final |
'r+' | Lectura y escritura |
De la misma forma que para la lectura, existen dos formas distintas de escribir un archivo:
write(cadena)
writelines(lista_de_cadenas)
Asi como la función readline devuelve las líneas con los caracteres de fin de línea (\n
), será necesario agregar los caracteres de fin de línea a las cadenas que se vayan a escribir.
with open("saludo.py", "w") as saludo:
saludo.write("# Este programa fue generado por otro programa!\n")
saludo.write("print('Hola Mundo')\n")
Atención
Si un archivo existente se abre en modo lectura-escritura, al escribir en él se sobreescribirán los datos anteriores, a menos que se haya llegado al final del archivo.
log
archivo_log = open("log.txt", 'a')
# ...
# Hacer cosas que pueden dar error
error = "Formato de entrada invalido\n"
###
if error:
archivo_log.write("ERROR: " + error)
# ...
# Finalmente cerrar el archivo
archivo_log.close()
archivo_log = open("log.txt", 'a')
# ...
# Hacer cosas que pueden dar error
#Hardcodeo errores
error1 = "Formato de entrada invalido\n"
error2 = "No se pudo acceder al recurso\n"
lista_de_errores = ["ERROR: " + error1, "ERROR: " + error2]
###
if lista_de_errores:
archivo_log.writelines(lista_de_errores)
# ...
# Finalmente cerrar el archivo
archivo_log.close()
Escribir una función que reciba el nombre de un archivo y una temperatura, convierta la temperatura a Kelvin y Farenheit y escriba los 3 valores en el archivo.
exportar_conversion_temperaturas("tempraturas.txt", 37)
def celsius_a_kelvin(temp_celsius):
return temp_celsius + 273.15
def celsius_a_farenheit(temp_celsius):
return temp_celsius * (9/5) + 32
C:37
F:69
K:310.15
def celsius_a_kelvin(temp_celsius):
return temp_celsius + 273.15
def celsius_a_farenheit(temp_celsius):
return temp_celsius * (9/5) + 32
def exportar_conversion_temperaturas(nombre_salida, temp_c):
archivo = open(nombre_salida, "a")
temp_f = celsius_a_farenheit(temp_c)
temp_k = celsius_a_kelvin(temp_c)
lista_temp = ["C:" + str(temp_c) + '\n', "F:" + str(temp_f) + '\n', "K:" + str(temp_k) + '\n']
archivo.writelines(lista_temp)
exportar_conversion_temperaturas("tempraturas.txt", 37)
exportar_conversion_temperaturas("tempraturas.txt", 12)
El archivo de prueba “materias.txt” contiene un listado de materias.
Sabiendo que cada línea tiene el formato:
`ddcc – NOMBRE MATERIA`
Siendo dd el número del departamento y cc el código de la materia; se pide crear archivos de nombre dd.txt con un listado de los nombres de las materias de cada departamento.
import os
def exportar_materias_por_departamento():
# Itera por departamento.
materias_por_depto = {}
with open("materias.txt") as materias:
for materia in materias:
num_depto = materia[:2]
materia = materia[7:]
materias_por_depto[num_depto] = materias_por_depto.get(num_depto, []) + [ materia ]
# Exporta.
for depto in materias_por_depto:
with open(depto + ".txt", "w") as salida:
for materia in materias_por_depto[depto]:
salida.write(materia)
exportar_materias_por_departamento()
--------------------------------------------------------------------------- IOError Traceback (most recent call last) <ipython-input-28-b48104bd9c08> in <module>() 19 20 ---> 21 exportar_materias_por_departamento() <ipython-input-28-b48104bd9c08> in exportar_materias_por_departamento() 5 # Itera por departamento. 6 materias_por_depto = {} ----> 7 with open("materias.txt") as materias: 8 for materia in materias: 9 num_depto = materia[:2] IOError: [Errno 2] No such file or directory: 'materias.txt'
Un formato que suele usarse para transferir datos es CSV (comma separated values): valores separados por comas.
Un ejemplo:
Nombre,Apellido,Telefono,Cumpleaños
"John","Smith","555-0101","1973-11-24"
"Jane","Smith","555-0101","1975-06-12"
csv.reader()
: devuelve un iterable con una lista por iteración.csv.DictReader()
: devuelve un iterable con un diccionario por iteración.csv.writer()
archivo.writerow()
archivo.writerows()
csv.DictWriter()
import csv
def guardar_puntajes(nombre_archivo, puntajes):
"""Guarda la lista de puntajes en el archivo."""
with open(nombre_archivo, "w") as f:
archivo_csv = csv.writer(f)
archivo_csv.writerow(["Nombre", "Puntaje", "Tiempo"])
archivo_csv.writerows(puntajes)
def recuperar_puntajes(nombre_archivo):
"""Recupera los puntajes a partir del archivo provisto."""
puntajes = []
with open(nombre_archivo, "r") as f:
archivo_csv = csv.reader(f)
archivo_csv.next()
for nombre, puntaje, tiempo in archivo_csv:
puntajes.append((nombre, int(puntaje), tiempo))
return puntajes
guardar_puntajes("archivo.csv", [["Miguel",424,323], ["Mati",423,121]])
puntajes = recuperar_puntajes("archivo.csv")
print puntajes
[('Miguel', 424, '323'), ('Mati', 423, '121')]
Escribir en un archivo csv la tabla de información del directorio en donde se encuentra el script. En el formato:
Nombre, Tipo, Tamaño
Tipo:
`a`: si es un archivo
`d`: si es un directorio
Ayuda:
import csv
import os
def obtener_tipo(nombre_archivo):
''' Devuelve 'a' en caso de que el nombre pasado por parámetro
sea un archivo, 'd' en caso de que sea un directorio.
'''
return 'a' if os.path.isfile(nombre_archivo) else 'd'
def exportar_info_directorio_prueba(archivo_salida):
with open(archivo_salida, 'w') as archivo:
salida = csv.writer(archivo, lineterminator='\n')
salida.writerow(["Nombre", "Tipo", "Tamaño"])
for archivo in os.listdir("."):
salida.writerow([archivo, obtener_tipo(archivo), os.path.getsize(archivo)])
exportar_info_directorio_prueba("salida.txt")
El archivo “paises.csv” contiene información relacionada a los paises del mundo. Escribir en un nuevo archivo csv un listado ordenado alfabéticamente de los nombres de los paises que empiezan con “A” y sus capitales.
import csv
import os
def obtener_datos_paises_con_a():
# Itera por pais.
paises_con_a = []
with open("paises.csv") as archivo_paises:
paises = csv.DictReader(archivo_paises)
for pais in paises:
if pais['Common Name'][0] in ('a', 'A'):
paises_con_a.append([pais['Common Name'], pais['Capital']])
paises_con_a.sort(key = lambda p: p[0])
with open("salida.csv", 'w') as archivo_salida:
salida = csv.writer(archivo_salida, lineterminator='\n')
salida.writerows(paises_con_a)
obtener_datos_paises_con_a()
El módulo pickle implementa un algoritmo que permite serializar y de-serializar structuras de objetos de Python.
"Pickling" es el proceso por el cual una jerarquía de objetos de Python es convertida en un stream de bytes.
"Unpickling" es el proceso inverso, en el cual a partir de un stream de bytes se obtiene una jerarquía de objetos.
Para usar esta librería se debe importar:
import pickle
Los archivos generados solo funcionan para Python!.
dump(obj, file, protocol=None)
Recibe un objeto obj
de python, genera un stream de bytes que lo represente y lo guarda en el archivo abierto file
(con permisos de escritura).
load(file)
Recibe un archivo abierto file
(con permisos de lectura) donde está guardado un stream de bytes asociado a un objeto de python, reconstruye el objeto original y lo devuelve.
import pickle
diccionario = { 'elemento1' : "elemento1",
'elemento2' : 2,
'elemento3' : (1,2,3),
'elemento4' : [1,2,3,4]}
pickle_out = open("dicc.pickle","wb")
pickle.dump(diccionario,pickle_out)
pickle_out.close()
import pickle
pickle_in = open("dicc.pickle","rb")
pickled_dicc = pickle.load(pickle_in)
pickle_in.close()
print pickled_dicc
{'elemento4': [1, 2, 3, 4], 'elemento1': 'elemento1', 'elemento2': 2, 'elemento3': (1, 2, 3)}
No se pueden serializar funciones lambda, ni nested functions.
Si se busca alta performance se recomienta usar cPickle ( import cPickle as pickle
)
Es un formato de archivos (open-standard) que usa text legible por las personas para transmitir datos que consisten en pares atributos-valor y arreglos (u otro valor serializable).
Si bien se deriva de JavaScript, JSON es un formato de datos independiente del lenguaje (al día de hoy la mayoría de los lenguajes pueden codificar y decodificar JSON).
La librería json
de Python usa una API similar a la de otras librerías como pickle
.
import json
dump(obj, file, <parámetros personalizables>)
Recibe un objeto obj
de python, serializa el objeto como un JSON
(usando la tabla de conversión) y lo guarda en el archivo abierto file
(con permisos de escritura).
load(file, <parámetros personalizables>)
Recibe un archivo abierto file
(con permisos de lectura) donde está guardado la serialización asociada a un objeto, deserializa (usando la tabal de conversión) y lo devuelve.
Python | JSON |
---|---|
dict | object |
list, tuple | array |
str, unicode | string |
int, long, float | number |
True | true |
False | false |
None | null |
JSON | Python |
---|---|
object | dict |
array | list |
string | unicode |
number (int) | int, long |
number | (real) float |
true | True |
false | False |
null | None |
import json
diccionario = { 'elemento1' : "elemento1",
'elemento2' : 2,
'elemento3' : (1,2,3),
'elemento4' : [1,2,3,4]}
json_out = open("dicc.json","w")
json.dump(diccionario,json_out)
json_out.close()
import json
json_in = open("dicc.json","r")
json_dicc = json.load(json_in)
json_in.close()
print json_dicc
#Observaciones:
# Las tuplas se serializan/deserializan como listas
# Los strings se serializan/deserializan como unicodes
{u'elemento4': [1, 2, 3, 4], u'elemento1': u'elemento1', u'elemento2': 2, u'elemento3': [1, 2, 3]}
import json
class ClaseDePrueba(object):
def __init__(self, a, b):
self.a = a
self.b = b
class JSONEncoderClaseDePrueba(json.JSONEncoder):
def default(self, obj):
if (isinstance(obj,ClaseDePrueba)):
#return {"a":obj.a, "b":obj.b}
# La siguiente linea la veremos en detalle luego
return {"a":obj.a, "b":obj.b, "_type": "ClaseDePrueba"}
# Let the base class default method raise the TypeError
return super().default(obj)
instancia = ClaseDePrueba(1,2)
json_out = open("instancia.json","w")
json.dump(instancia,json_out,cls = JSONEncoderClaseDePrueba)
json_out.close()
json_in = open("instancia.json","r")
json_instancia = json.load(json_in)
json_in.close()
print json_instancia
{u'a': 1, u'_type': u'ClaseDePrueba', u'b': 2}
def object_hook_ClaseDePrueba(o):
if "_type" not in o:
return o
tipo = o["_type"]
if tipo == "ClaseDePrueba":
return ClaseDePrueba(o["a"],o["b"])
return o
json_in = open("instancia.json","r")
json_instancia = json.load(json_in, object_hook = object_hook_ClaseDePrueba)
json_in.close()
print type(json_instancia)
print json_instancia.a
print json_instancia.b
<class '__main__.ClaseDePrueba'> 1 2