Esperando 🐍
Datos de COLOR
Datos de COLOR 2
Datos de COLOR 2:
La Libreria Estandar
Antes de comenzar
Figuro anotado en la carrera de Lic. en Informatica
Escucho mucha musica (y a gente que lo intenta)
Tomo mate hasta caminando (amargo e hirviendo, claramente)
Me gusta Python (pero hago web en JavaSript)
Entonces, que es "Libreria Estandar"?
Entonces, que es "Libreria Estandar"?
Son los modulos/paquetes que vienen con el lenguaje al momento de instalarlo
Son los modulos/paquetes que vienen con el lenguaje al momento de instalarlo
Con el fin de solucionar problemas comunes
Con el fin de solucionar problemas comunes
Esos que podes importar sin un
pip install <libreria>En Python, son muchos
En Python, son muchos
En esta charla, vamos a ver algunos
En Python, son muchos
En esta charla, vamos a ver algunos
Para aprender o recordar algunos
Pero, que decis con "dato de color"?
Pero, que decis con "dato de color"?
Son esas cosas/informacion que uno sabe, por curiosidad, por experiencia o que ni te acordas de donde pero lo sabes
Son esas cosas/informacion que uno sabe, por curiosidad, por experiencia o que ni te acordas de donde pero lo sabes
Y que en algun escenario hipotetico a alguien le sirve
Ahora si, comenzamos?
import pathlib
import pathlib
Interfaz orientada a objetos para manipular rutas de archivos y directorios


Que dice el grafico?

Que depende de donde se ejecute el codigo, Path instanciara el objeto para el SO subyacente
Entonces felizmente usamos Path y es cross-platform
import pathlib
path = pathlib.Path('.')
for p in path.iterdir():
print(p)
.venv
presentation
sections
sys.html
test.py
xd.py
Solo para listar?
A ver la magia
import pathlib
path = pathlib.Path('c:/')
path = path / 'Windows' / 'System32'
print(*path.glob('m*o*d*u*l*o*'), sep="\n")
c:\Windows\System32\MediaFoundation.DefaultPerceptionProvider.dll
O algo mas simple
import pathlib
print(pathlib.Path.cwd())
C:\Users\suare\projects\personal\pyday
O algo comodo como
import pathlib
path = pathlib.Path('.')
with path.joinpath('.env').open() as f:
print(f.read())
DB_URI=postgresql://por:quemeestas@localhost:5432/leyendo
OPENAPI_KEY=sk_test_4eC39HqLyjWDarjtT1zdp7dc
OAUTH_CLIENT_ID=1234567890-abcdefghijklmnopqrstuvwxyz.apps.googleusercontent.com
OAUTH_CLIENT_SECRET=GOCSPX-abcdefgHIJKLMNopqrstuvwxyz12345
import inspect
import inspect
Inspeccion de objetos vivos como
clases, funciones, metodos, modulos, trazas de pila, marcos y codigo fuente
Ver las funciones de un modulo
import inspect
import secrets
print("nativas:", *inspect.getmembers(secrets, inspect.isbuiltin), sep="\n ")
print("normal:", *inspect.getmembers(secrets, inspect.isfunction), sep="\n ")
nativas:
('compare_digest', <built-in function compare_digest>)
normal:
('randbelow', <function randbelow at 0x000001C268038400>)
('token_bytes', <function token_bytes at 0x000001C2680398A0>)
('token_hex', <function token_hex at 0x000001C26803BEC0>)
('token_urlsafe', <function token_urlsafe at 0x000001C26803BF60>)
No falta la funcion secrets.choice?
No falta la funcion secrets.choice?
import inspect
import secrets
print("normal:", *inspect.getmembers(secrets, inspect.ismethod), sep="\n ")
import inspect
import secrets
print("normal:", *inspect.getmembers(secrets, inspect.ismethod), sep="\n ")
metodo:
('choice', <bound method Random.choice of <random.SystemRandom object at 0x000001EB6ED0BE60>>)
('randbits', <bound method SystemRandom.getrandbits of <random.SystemRandom object at 0x000001EB6ED0BE60>>)
Ver la documentacion de un objeto
import inspect
print(inspect.getdoc(inspect))
import inspect
print(inspect.getdoc(inspect))
Generate cryptographically strong pseudo-random numbers suitable for
managing secrets such as account authentication, tokens, and similar.
See PEP 506 for more information.
https://peps.python.org/pep-0506/
Ver el codigo fuente de un objeto
import inspect
print(inspect.getsource(inspect.SystemRandom))
class SystemRandom(Random):
"""Alternate random number generator using sources provided
by the operating system (such as /dev/urandom on Unix or
CryptGenRandom on Windows).
Not available on all systems (see os.urandom() for details).
"""
def random(self):
"""Get the next random number in the range 0.0 <= X < 1.0."""
return (int.from_bytes(_urandom(7)) >> 3) * RECIP_BPF
...
def seed(self, *args, **kwds):
"Stub method. Not used for a system random number generator."
return None
def _notimplemented(self, *args, **kwds):
"Method should not be called for a system random number generator."
raise NotImplementedError('System entropy source does not have state.')
getstate = setstate = _notimplemented
Ver el codigo fuente de una funcion
import inspect
print(inspect.getsource(print))
Traceback (most recent call last):
File "C:\Users\suare\projects\personal\pyday\xd.py", line 25, in <module>
print(inspect.getsource(print))
^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\suare\.pyenv\pyenv-win\versions\3.12.1\Lib\inspect.py",
line 1282, in getsource
lines, lnum = getsourcelines(object)
^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\suare\.pyenv\pyenv-win\versions\3.12.1\Lib\inspect.py",
line 1264, in getsourcelines
lines, lnum = findsource(object)
^^^^^^^^^^^^^^^^^^
File "C:\Users\suare\.pyenv\pyenv-win\versions\3.12.1\Lib\inspect.py",
line 1075, in findsource
file = getsourcefile(object)
^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\suare\.pyenv\pyenv-win\versions\3.12.1\Lib\inspect.py",
line 952, in getsourcefile
filename = getfile(object)
^^^^^^^^^^^^^^^
File "C:\Users\suare\.pyenv\pyenv-win\versions\3.12.1\Lib\inspect.py",
line 932, in getfile
raise TypeError('module, class, method, function, traceback, frame, or '
TypeError: module, class, method, function, traceback, frame, or code object
was expected, got builtin_function_or_method
Cuidado con codigo nativo, hay cosas que no se pueden ver
Ver componentes de una funcion
import inspect
def BuenEjemplo(a, b: int, c: str = "algo", **kwargs) -> int:
"""Esta es un muy buen ejemplo."""
return a + b + c
signature = inspect.signature(BuenEjemplo)
print(signature.parameters)
print(signature.return_annotation)
OrderedDict({
'a': <Parameter "a">,
'b': <Parameter "b: int">,
'c': <Parameter "c: str = 'hola'">,
'kwargs': <Parameter "**kwargs">
})
<class 'int'>
import atexit
import atexit
Registrar funciones de limpieza para ejecutar cuando el programa termina
import atexit
def chau():
print("termine la ejecucion 👌")
atexit.register(chau)
import atexit
def chau():
print("termine la ejecucion 👌")
atexit.register(chau)
termine la ejecucion 👌
De que es util?
De que es util?
Para guardar logs, cerrar conexiones, liberar recursos, etc
Si, pero no es lo mismo que un finally o usar un context manager?
Si, pero no es lo mismo que un finally o usar un context manager?
No, finally o context manager se ejecutan siempre, atexit solo si el interprete termina normalmente o se llama a exit() o sys.exit()
Se pueden registrar multiples funciones
Se pueden registrar multiples funciones
Se ejecutan en orden inverso al que se registraron
import atexit
primera = lambda: print("primera")
segunda = lambda: print("segunda")
otra = lambda x: print(x)
atexit.register(primera)
atexit.register(segunda)
atexit.register(otra, "tercera")
tercera
segunda
primera
Y si queremos des-registrar una funcion?
Y si queremos des-registrar una funcion?
atexit.unregister(<una_funcion>)
import atexit
desapareci = lambda name: print(f"{name} desapareci")
me_quede = lambda name: print(f"{name} me_quede")
atexit.register(desapareci, "primera")
atexit.register(me_quede, "segunda")
atexit.register(desapareci, name="tercera")
atexit.unregister(desapareci)
import atexit
desapareci = lambda name: print(f"{name} desapareci")
me_quede = lambda name: print(f"{name} me_quede")
atexit.register(desapareci, "primera")
atexit.register(me_quede, "segunda")
atexit.register(desapareci, name="tercera")
atexit.unregister(desapareci)
segunda me_quede
import doctest
import doctest
Validar ejemplos en las docstrings de un modulo, tal que representen la implementacion
def baskara(a, b, c):
"""
Calcula las raices de una ecuacion cuadratica
>>> baskara(1, 0, -1)
(1.0, -1.0)
>>> baskara(1, 0, 1)
Traceback (most recent call last):
...
ValueError: math domain error
"""
from math import sqrt
x1 = (-b + sqrt(b**2 - 4*a*c)) / (2*a)
x2 = (-b - sqrt(b**2 - 4*a*c)) / (2*a)
return x1, x2
if __name__ == "__main__":
import doctest
doctest.testmod()
python mi_modulo.py
Y el resultado?
Y el resultado?
Si el resultado esta bien, no se imprime nada
Y el resultado?
Si el resultado esta bien, no se imprime nada
Sino, se imprime el reporte de errores
Para ver que esta pasando, podemos usar el flag -v
Para ver que esta pasando, podemos usar el flag -v
python mi_modulo.py -v
python mi_modulo.py -v
Trying:
baskara(1, 0, -1)
Expecting:
(1.0, -1.0)
ok
Trying:
baskara(1, 0, 1)
Expecting:
Traceback (most recent call last):
...
ValueError: math domain error
ok
1 items had no tests:
__main__
1 items passed all tests:
2 tests in __main__.baskara
2 tests in 2 items.
2 passed and 0 failed.
Test passed.
O podemos correr los tests de un modulo
""">>> count_letters("me leiste")
{'m': 1, 'e': 3, 'l': 1, 'i': 1, 's': 1, 't': 1}
"""
import collections
import string
def count_letters(text: str):
""">>> count_letters("hola")
{'h': 1, 'o': 1, 'l': 1, 'a': 1}
>>> count_letters(43)
Traceback (most recent call last):
...
ValueError: text must be a string
"""
normalized_text = "".join(c for c in text.lower() if c in string.ascii_lowercase)
return {**collections.Counter(normalized_text)}
python -m doctest counter.py
**********************************************************************
File "C:\Users\suare\projects\personal\pyday\counter.py", line 15, in counter.count_letters
Failed example:
count_letters(43)
Expected:
Traceback (most recent call last):
...
ValueError: text must be a string
Got:
Traceback (most recent call last):
File "C:\Users\suare\.pyenv\pyenv-win\versions\3.12.1\Lib\doctest.py", line 1359, in __run
exec(compile(example.source, filename, "single",
File "<doctest counter.count_letters[1]>", line 1, in <module>
count_letters(43)
File "C:\Users\suare\projects\personal\pyday\counter.py", line 20, in count_letters
normalized_text = "".join(c for c in text.lower() if c in string.ascii_lowercase)
^^^^^^^^^^
AttributeError: 'int' object has no attribute 'lower'
**********************************************************************
1 items had failures:
1 of 2 in counter.count_letters
***Test Failed*** 1 failures.
Uh, no paso el test
Uh, no paso el test
Falto validar que el argumento sea un string
""">>> count_letters("me leiste")
{'m': 1, 'e': 3, 'l': 1, 'i': 1, 's': 1, 't': 1}
"""
import collections
import string
def count_letters(text: str):
""">>> count_letters("hola")
{'h': 1, 'o': 1, 'l': 1, 'a': 1}
>>> count_letters(43)
Traceback (most recent call last):
...
ValueError: text must be a string
"""
if not isinstance(text, str):
raise ValueError("text must be a string")
normalized_text = "".join(c for c in text.lower() if c in string.ascii_lowercase)
return {**collections.Counter(normalized_text)}
python -m doctest counter.py
doctest prima la exactitud
doctest prima la exactitud
Hay casos donde no es lo que queremos, ya que el resultado esta simplificado
doctest prima la exactitud
Hay casos donde no es lo que queremos, ya que el resultado esta simplificado
Para eso podemos usar flags
Para eso podemos usar flags
def numeros():
""">>> numeros()
[1, 2, ..., 10]
"""
return list(range(1, 11))
if __name__ == "__main__":
import doctest
doctest.testmod(optionflags=doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE)
python numeros.py
O como modulo
python -m doctest -o ELLIPSIS -o NORMALIZE_WHITESPACE numeros.py
Podemos extraer un script desde los ejemplos
Podemos extraer un script desde los ejemplos
import doctest
print(doctest.script_from_examples(r"""
Este es un ejemplo sencillo
>>> def suma(a, b):
... return a + b
>>> suma(1, 2)
3
o tambien se puede hacer con un lambda
>>> resta = lambda a, b: a - b
>>> resta(2, 1)
1
"""))
Podemos extraer un script desde los ejemplos
# Este es un ejemplo sencillo
def suma(a, b):
return a + b
suma(1, 2)
# Expected:
## 3
#
# o tambien se puede hacer con un lambda
#
resta = lambda a, b: a - b
resta(2, 1)
# Expected:
## 1
import shutil
import shutil
Utilidades simples para manipular archivos y directorios
Utilidades simples para manipular archivos y directorios
Mas comodas que usar os y os.path
Simples?
Simples?
Como?
Asi
import shutil
shutil.copy('test.py', 'test2.py')
import shutil
shutil.copy('test.py', 'test2.py')
ls
no_tengo_cosas tengo_cosas test.py
python test.py
ls
no_tengo_cosas tengo_cosas test.py test2.py
Ah, hay cosas ahi?
Ah, hay cosas ahi?
tree
.
├─test.py
├─test2.py
├─no_tengo_cosas
│ ├─estoy_vacio
│ └─no_estoy
│ └─yo_tampoco.md
└─tengo_cosas
Arreglemos eso
Arreglemos eso
import shutil
shutil.copytree('no_tengo_cosas', 'tengo_cosas', dirs_exist_ok=True)
python test.py
tree
.
├─test.py
├─test2.py
├─no_tengo_cosas
│ ├─estoy_vacio
│ └─no_estoy
│ └─yo_tampoco.md
└─tengo_cosas
├─estoy_vacio
└─no_estoy
└─yo_tampoco.md
python test.py
tree
.
├─test.py
├─test2.py
├─no_tengo_cosas
│ ├─estoy_vacio
│ └─no_estoy
│ └─yo_tampoco.md
└─tengo_cosas
├─estoy_vacio
└─no_estoy
└─yo_tampoco.md
Uh lo duplicamos
Solucionado
import shutil
shutil.rmtree('no_tengo_cosas')
python test.py
tree
.
├─test.py
├─test2.py
└─tengo_cosas
├─estoy_vacio
└─no_estoy
└─yo_tampoco.md
Para para para, pero hay muchos archivos
Para para para, pero hay muchos archivos
import shutil
shutil.move('tengo_cosas', 'comprimido')
shutil.move('test.py', 'comprimido')
shutil.move('test2.py', 'comprimido')
shutil.make_archive('comprimido', 'zip', 'comprimido')
shutil.rmtree('comprimido')
import shutil
shutil.move('tengo_cosas', 'comprimido')
shutil.move('test.py', 'comprimido')
shutil.move('test2.py', 'comprimido')
shutil.make_archive('comprimido', 'zip', 'comprimido')
shutil.rmtree('comprimido')
python test.py
tree
.
└─comprimido.zip
Ahora si
Me pregunto donde esta el comando tree
Me pregunto donde esta el comando tree
import shutil
shutil.which('tree')
import shutil
shutil.which('tree')
python test.py
C:\Windows\system32\tree.COM
python test.py
C:\Windows\system32\tree.COM
Ah mira, esta en system32
Ah mira, esta en system32
Mejor dejemos de jugar
Ah mira, esta en system32
Mejor dejemos de jugar
siguiente modulo 🙃
import sqlite3
import sqlite3
Trabajar con bases de datos SQLite
Trabajar con bases de datos SQLite
locales
Simple, rapido, y facil de usar
Simple, rapido, y facil de usar
import sqlite3
con = sqlite3.connect('example.db')
cur = con.cursor()
cur.execute("CREATE TABLE chiki (nombre TEXT, edad INTEGER)")
print(cur.execute("SELECT name FROM sqlite_master").fetchall())
import sqlite3
con = sqlite3.connect('example.db')
cur = con.cursor()
cur.execute("CREATE TABLE chiki (nombre TEXT, edad INTEGER)")
print(cur.execute("SELECT name FROM sqlite_master").fetchall())
[('chiki',)]
chikis = [
('Guido van Rossum', 68),
('Raymond Hettinger', 50),
('Brett Cannon', 45)
]
cur.executemany("INSERT INTO chiki VALUES (?, ?)", chikis)
con.commit()
print(cur.execute("SELECT * FROM chiki WHERE edad >= 50").fetchall())
chikis = [
('Guido van Rossum', 68),
('Raymond Hettinger', 50),
('Brett Cannon', 45)
]
cur.executemany("INSERT INTO chiki VALUES (?, ?)", chikis)
con.commit()
print(cur.execute("SELECT * FROM chiki WHERE edad >= 50").fetchall())
[('Guido van Rossum', 68), ('Raymond Hettinger', 50)]
No te olvides de cerrar la conexion
No te olvides de cerrar la conexion
con.close()
No te olvides de cerrar la conexion
con.close()
Pero tampoco te olvides de usar commit
No te olvides de cerrar la conexion
con.commit()
con.close()
Pero tampoco te olvides de usar commit
Genial, ahora ya sabes como trabajar con SQLite en Python
Algo mas?
Algo mas?
import sqlite3
con = sqlite3.connect(':memory:')
cur = con.cursor()
cur.execute("CREATE TABLE temp (msg TEXT)")
cur.execute("INSERT INTO temp VALUES ('Solo en memoria')")
cur.execute("INSERT INTO temp VALUES (', en otros terminos, no persistente')")
print("".join(*cur.execute("SELECT * FROM temp").fetchall()))
import sqlite3
con = sqlite3.connect(':memory:')
cur = con.cursor()
cur.execute("CREATE TABLE temp (msg TEXT)")
cur.execute("INSERT INTO temp VALUES ('Solo en memoria')")
cur.execute("INSERT INTO temp VALUES (', en otros terminos, no persistente')")
print("".join(*cur.execute("SELECT * FROM temp").fetchall()))
Solo en memoria, en otros terminos, no persistente
Algo mas?
Algo mas?
import sqlite3
original = sqlite3.connect('example.db')
nueva = sqlite3.connect(':memory:')
original.backup(nueva)
original.close()
nueva.close()
import sqlite3
original = sqlite3.connect('example.db')
nueva = sqlite3.connect(':memory:')
original.backup(nueva)
original.close()
nueva.close()
Creanme que hace el backup bien
Un poco de error handling no vendria mal
Un poco de error handling no vendria mal
import sqlite3
con = sqlite3.connect(':memory:')
cur = con.cursor()
cur.execute("CREATE TABLE escribime_bien (msg TEXT)")
try:
cur.execute("INSERT INTO escribime_mal VALUES ('no_quiero')")
except sqlite3.Error as e:
print("capturamos un error, no se cual")
finally:
con.close()
import sqlite3
con = sqlite3.connect(':memory:')
cur = con.cursor()
cur.execute("CREATE TABLE escribime_bien (msg TEXT)")
try:
cur.execute("INSERT INTO escribime_mal VALUES ('no_quiero')")
except sqlite3.Error as e:
print("capturamos un error, no se cual")
finally:
con.close()
capturamos un error, no se cual
capturamos un error, no se cual
Tranquilos, hay mas especificos
Tranquilos, hay mas especificos
import sqlite3
print(*(
"sqlite3" + name
for name in dir(sqlite3)
if "Error" in name
))
import sqlite3
print(*(
"sqlite3" + name
for name in dir(sqlite3)
if "Error" in name
))
sqlite3.DataError sqlite3.DatabaseError sqlite3.Error sqlite3.IntegrityError
sqlite3.InterfaceError sqlite3.InternalError sqlite3.NotSupportedError
sqlite3.OperationalError sqlite3.ProgrammingErro
import sys
import sys
Acceso a variables usadas/mantenidas por el interprete y funciones para interactuar con este
Veamos algunas
Veamos algunas
import sys
print(sys.argv)
Veamos algunas
import sys
print(sys.argv)
python xd.py $HOME "argumento 2"
['xd.py', 'C:\\Users\\suare', 'argumento 2']
Veamos algunas
import sys
print(sys.orig_argv)
Veamos algunas
import sys
print(sys.orig_argv)
python xd.py $HOME "argumento 2"
[
'C:\\Users\\suare\\.pyenv\\pyenv-win\\versions\\3.12.1\\python.exe',
'xd.py', 'C:\\Users\\suare', 'argumento 2'
]
Veamos algunas
import sys
print(sys.byteorder)
Veamos algunas
import sys
print(sys.byteorder)
python xd.py
little
Veamos algunas
import sys
print(len(sys.builtin_module_names))
print(len(sys.stdlib_module_names))
print(len(sys.modules))
Veamos algunas
import sys
print(len(sys.builtin_module_names))
print(len(sys.stdlib_module_names))
print(len(sys.modules))
67
300
35
Veamos algunas
import sys
print(sys.path)
Veamos algunas
import sys
print(sys.path)
Es la lista de directorios donde Python busca modulos, prepopulada con la variable de entorno PYTHONPATH y un por defecto que depende del sistema subyacente
Veamos algunas
import sys
print(sys.copyright)
Veamos algunas
import sys
print(sys.copyright)
Copyright (c) 2001-2023 Python Software Foundation.
All Rights Reserved.
Copyright (c) 2000 BeOpen.com.
All Rights Reserved.
Copyright (c) 1995-2001 Corporation for National Research Initiatives.
All Rights Reserved.
Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam.
All Rights Reserved.
Veamos algunas
import sys
print(sys.implementation)
print(sys.platform)
print(sys.version)
print(sys.getrecursionlimit())
Veamos algunas
import sys
print(sys.implementation)
print(sys.platform)
print(sys.version)
print(sys.getrecursionlimit())
namespace(
name='cpython', cache_tag='cpython-312',
version=sys.version_info(major=3, minor=12, micro=1, releaselevel='final', serial=0),
hexversion=51118576)
win32
3.12.1 (tags/v3.12.1:2305ca5, Dec 7 2023, 22:03:25) [MSC v.1937 64 bit (AMD64)]
1000
Veamos algunas
import sys
x = 1
y = [x, 2, 3]
z = {'x': x, 'y': y}
print(sys.getsizeof(x))
print(sys.getrefcount(x))
Veamos algunas
import sys
x = 1
y = [x, 2, 3]
z = {'x': x, 'y': y}
print(sys.getsizeof(x))
print(sys.getrefcount(x))
28
4294967295
Veamos algunas
import sys
x = 1
y = [x, 2, 3]
z = {'x': x, 'y': y}
print(sys.getrefcount(y))
Veamos algunas
import sys
x = 1
y = [x, 2, 3]
z = {'x': x, 'y': y}
print(sys.getrefcount(y))
3
import tempfile
import tempfile
Crear archivos y directorios temporales
Crear archivos y directorios temporales
De que nos sirve?
De que nos sirve?
Para trabajar con grandes volumenes de datos, haciendo transformaciones y otras operaciones que no necesitamos persistir en disco
Para trabajar con grandes volumenes de datos, haciendo transformaciones y otras operaciones que no necesitamos persistir en disco
Es ahi donde entra tempfile y nos simplifica la vida
Es ahi donde entra tempfile y nos simplifica la vida
import tempfile
with tempfile.TemporaryFile() as f:
f.write(b'hello world')
f.seek(0)
print(f.read())
import tempfile
with tempfile.TemporaryFile() as f:
f.write(b'hello world')
f.seek(0)
print(f.read())
b'hello world'
Por defecto, los archivos son abiertos en modo w+b
Por defecto, los archivos son abiertos en modo w+b
Con mode=<modo apertura> se puede cambiar
Con las funciones
tempfile.mkstemp se crea un archivo temporal
tempfile.mkdtemp se crea un directorio temporal
Con las funciones
tempfile.mkstemp se crea un archivo temporal
tempfile.mkdtemp se crea un directorio temporal
Pero hay que hacer la limpieza manualmente
Por lo que es mejor usar
tempfile.TemporaryFile, tempfile.NamedTemporaryFile y tempfile.TemporaryDirectory
Por lo que es mejor usar
tempfile.TemporaryFile, tempfile.NamedTemporaryFile y tempfile.TemporaryDirectory
Ya que al ser context managers, hacen el cierre y eliminacion del archivo/directorio automaticamente
import os
import tempfile
with tempfile.NamedTemporaryFile() as f:
print(f.name)
print(os.path.exists(f.name))
print(os.path.exists(f.name))
import os
import tempfile
with tempfile.NamedTemporaryFile() as f:
print(f.name)
print(os.path.exists(f.name))
print(os.path.exists(f.name))
C:\Users\suare\AppData\Local\Temp\tmpkjh2rj8i
True
False
Algo totalmente innecesario
Algo totalmente innecesario
import os
import tempfile
with tempfile.TemporaryDirectory() as d:
for i in range(100):
with open(f'{d}/file_{_}.txt', 'w') as f:
f.write(f'Hola soy el archivo {i}')
print(sum(
os.path.getsize(f)
for f in os.listdir(d)
if os.path.isfile(f)
))
import os
import tempfile
with tempfile.TemporaryDirectory() as d:
for i in range(100):
with open(f'{d}/file_{_}.txt', 'w') as f:
f.write(f'Hola soy el archivo {i}')
print(sum(
os.path.getsize(f)
for f in os.listdir(d)
if os.path.isfile(f)
))
0
import os
import tempfile
with tempfile.TemporaryDirectory() as d:
for i in range(100):
with open(f'{d}/file_{_}.txt', 'w') as f:
f.write(f'Hola soy el archivo {i}')
print(sum(
os.path.getsize(f)
for f in os.listdir(d)
if os.path.isfile(f)
))
Como que pesa 0?
import os
import tempfile
with tempfile.TemporaryDirectory() as d:
for i in range(100):
with open(f'{d}/file_{_}.txt', 'w') as f:
f.write(f'Hola soy el archivo {i}')
print(sum(
os.path.getsize(f)
for f in os.listdir(d)
if os.path.isfile(f)
))
Me falto el d/ en el os.path.getsize(f) e if os.path.isfile(f)
import os
import tempfile
with tempfile.TemporaryDirectory() as d:
for i in range(100):
with open(f'{d}/file_{_}.txt', 'w') as f:
f.write(f'Hola soy el archivo {i}')
print(sum(
os.path.getsize(f"{d}/{f}")
for f in os.listdir(d)
if os.path.isfile(f"{d}/{f}")
))
Ahora si
import os
import tempfile
with tempfile.TemporaryDirectory() as d:
for i in range(100):
with open(f'{d}/file_{_}.txt', 'w') as f:
f.write(f'Hola soy el archivo {i}')
print(sum(
os.path.getsize(f"{d}/{f}")
for f in os.listdir(d)
if os.path.isfile(f"{d}/{f}")
))
2190
import timeit
import timeit
Medir tiempo de ejecucion de pequeños fragmentos de codigo, de forma simple
import timeit
print(timeit.timeit('8 / 2 * (2 + 2)'), "segundos")
import timeit
print(timeit.timeit('8 / 2 * (2 + 2)'), "segundos")
0.014247099999920465 segundos
import timeit
print(timeit.timeit('8 / 2 * (2 + 2)'), "segundos")
0.014247099999920465 segundos
Esta bien, que mas?
Permite definir el número de muestras
timeit.timeit(number=<default 1_000_000>)
Permite definir la funcion de tiempo
timeit.timeit(timer=<default time.perf_counter>)
Permite definir la funcion de tiempo
timeit.timeit(timer=<default time.perf_counter>)
Algunas opciones
time.perf_counter
time.perf_counter_ns
time.process_time
Permite repetir la medicion
timeit.repeat(repeat=<default 5>)
Permite repetir la medicion
timeit.repeat(repeat=<default 5>)
Util para acercarnos al lower bound
Si lo juntamos todo
Si lo juntamos todo
import time
import timeit
medidas = timeit.repeat(
"pow(2, 200)",
number=1_000,
repeat=100,
timer=time.perf_counter_ns
)
print(len(medidas), "mediciones")
print(min(medidas), "ns")
import time
import timeit
medidas = timeit.repeat(
"pow(2, 200)",
number=1_000,
repeat=100,
timer=time.perf_counter_ns
)
print(len(medidas), "mediciones")
print(min(medidas), "ns")
100 mediciones
240900 ns
Para casos mas complejos, estan los parametros setup o globals
Para casos mas complejos, estan los parametros setup o globals
setup se ejecuta una vez antes de cada medicion
Para casos mas complejos, estan los parametros setup o globals
setup se ejecuta una vez antes de cada medicion
globals se usa para pasar el contexto de ejecucion
globals se usa para pasar el contexto de ejecucion
import timeit
msj = 'un caso de prueba' * 100
s1 = 'sum(map(ord, msj))'
s2 = '''x = 0
for c in msj:
x += ord(c)
'''
s3 = 'sum(msj.encode("utf-8"))'
print(timeit.timeit(s1, globals=globals()))
print(timeit.timeit(s2, globals=globals()))
print(timeit.timeit(s3, globals=globals()))
import timeit
msj = 'un caso de prueba' * 100
s1 = 'sum(map(ord, msj))'
s2 = '''x = 0
for c in msj:
x += ord(c)
'''
s3 = 'sum(msj.encode("utf-8"))'
print(timeit.timeit(s1, globals=globals()))
print(timeit.timeit(s2, globals=globals()))
print(timeit.timeit(s3, globals=globals()))
36.25424589999966
90.68637050000143
8.36053659999925
Hay una mas rapida?
Hay una mas rapida?
Mirando bien el escenario a medir
Mirando bien el escenario a medir
import timeit
msj = 'un caso de prueba' * 100
s4 = """\
slice_len = len(msj) // 100
slice = msj[:slice_len].encode('utf-8')
sum(slice) * 100
"""
print(timeit.timeit(s4, globals=globals()))
import timeit
msj = 'un caso de prueba' * 100
s4 = """\
slice_len = len(msj) // 100
slice = msj[:slice_len].encode('utf-8')
sum(slice) * 100
"""
print(timeit.timeit(s4, globals=globals()))
0.42981549999967683
Casi me olvido
Casi me olvido
Tambien puede ser usado desde la terminal
Tambien puede ser usado desde la terminal
python -m timeit -s "import math; x=48; y=-1.9" "math.copysign(x, y)"
Tambien puede ser usado desde la terminal
python -m timeit -s "import math; x=48; y=-1.9" "math.copysign(x, y)"
2000000 loops, best of 5: 114 nsec per loop
Tambien puede ser usado desde la terminal
python -m timeit -s "import math; x=48; y=-1.9" "math.copysign(x, y)"
2000000 loops, best of 5: 114 nsec per loop
python -m timeit "x = 48; y = -1.9" "x * 1.0 if y > 0 else -1.0 * x"
Tambien puede ser usado desde la terminal
python -m timeit -s "import math; x = 48; y = -1.9" "math.copysign(x, y)"
2000000 loops, best of 5: 114 nsec per loop
python -m timeit "x = 48; y = -1.9" "x * 1.0 if y > 0 else -1.0 * x"
5000000 loops, best of 5: 91.8 nsec per loop
Esos fueron algunos modulos
Esos fueron algunos modulos
de 201 modulos listados en la documentacion de Python 3.12.6
Para que se den una idea
Solo vimos 9
import atexit | import doctest | import inspect |
import pathlib | import shutil | import sqlite3 |
import sys | import tempfile | import timeit |
Faltaron 65
Y otros 65
Y otros 61 mas
Les quedo tarea
Les quedo tarea
191 modulos para investigar
Les quedo tarea
191 modulos para investigar
Espero haber despertado su curiosidad
y que se animen a explorar la Libreria Estandar
O al menos
que vaya a saber dios la api que tiene...
O al menos
que se tomen un momento antes de buscar una libreria de terceros
que vaya a saber dios la api que tiene...
O al menos
que se tomen un momento antes de buscar una libreria de terceros
que vaya a saber dios la api que tiene...
Gracias por el espacio
Presentacion

Repositorio
