Content for Decem's Python course.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 451 lines 12 kB view raw
1{ 2 "cells": [ 3 { 4 "cell_type": "markdown", 5 "metadata": { 6 "slideshow": { 7 "slide_type": "slide" 8 } 9 }, 10 "source": [ 11 "## 9. Estructura de paquetes, módulos y ficheros." 12 ] 13 }, 14 { 15 "cell_type": "markdown", 16 "metadata": { 17 "slideshow": { 18 "slide_type": "slide" 19 } 20 }, 21 "source": [ 22 "### Ficheros y entrada/salida, apertura de ficheros e introducción de contextos." 23 ] 24 }, 25 { 26 "cell_type": "markdown", 27 "metadata": { 28 "slideshow": { 29 "slide_type": "fragment" 30 } 31 }, 32 "source": [ 33 "Para abrir un fichero usamos la función `open()`, que tiene como parámetros el nombre y ruta del fichero y el modo de apertura, una serie de caracteres que definen como se va a usar el fichero abierto.\n", 34 "\n", 35 "```python\n", 36 ">>> f = open('workfile', 'w')\n", 37 "```" 38 ] 39 }, 40 { 41 "cell_type": "markdown", 42 "metadata": { 43 "slideshow": { 44 "slide_type": "slide" 45 } 46 }, 47 "source": [ 48 "- `r` para solo lectura\n", 49 "- `w` para solo escritura, siendo borrado cualquier fichero que ya existiera\n", 50 "- `a` para añadir contenido al final del fichero\n", 51 "- `r+` para lectura y escritura" 52 ] 53 }, 54 { 55 "cell_type": "markdown", 56 "metadata": { 57 "slideshow": { 58 "slide_type": "slide" 59 } 60 }, 61 "source": [ 62 "Por defecto, si se omite el modo, se asume que es `r`. \n", 63 "\n", 64 "Además, también por defecto, un fichero se abre en modo texto, lo que significa que lee el contenido como cadenas de texto, aplicando transformaciones que dependen de la plataforma, como es la conversión de los salos de líneas, entre los formatos de Unix o de Windows, aplicando esta transformación tanto a la lectura como a la escritura.\n" 65 ] 66 }, 67 { 68 "cell_type": "markdown", 69 "metadata": { 70 "slideshow": { 71 "slide_type": "slide" 72 } 73 }, 74 "source": [ 75 "Para abrir en modo **binario** añadimos `b` al final de la cadena de texto que indica el modo." 76 ] 77 }, 78 { 79 "cell_type": "markdown", 80 "metadata": { 81 "slideshow": { 82 "slide_type": "slide" 83 } 84 }, 85 "source": [ 86 "La función `open` devuelve un descriptor que apunta al fichero, no el contenido. Una vez se deja de usar se tiene que llamar al método `f.close()` del descriptor para cerrar el fichero.\n" 87 ] 88 }, 89 { 90 "cell_type": "markdown", 91 "metadata": { 92 "slideshow": { 93 "slide_type": "slide" 94 } 95 }, 96 "source": [ 97 "Una buena práctica, para evitar la necesidad de cerrar el descriptor, es usar la palabra reservada `with`. Esto crea lo que se define en Python como un **contexto**.\n", 98 "\n", 99 "```python\n", 100 ">>> with open('workfile') as f:\n", 101 "... read_data = f.read()\n", 102 ">>> f.closed\n", 103 "True\n", 104 "```\n", 105 "\n", 106 "En este ejemplo, la variable `f` solo existe en el bloque que se ejecuta dentro del `with`, y se llama a `f.close()` una vez que la ejecución sale del bloque." 107 ] 108 }, 109 { 110 "cell_type": "markdown", 111 "metadata": { 112 "slideshow": { 113 "slide_type": "slide" 114 } 115 }, 116 "source": [ 117 "#### Lectura de contenido" 118 ] 119 }, 120 { 121 "cell_type": "markdown", 122 "metadata": { 123 "slideshow": { 124 "slide_type": "subslide" 125 } 126 }, 127 "source": [ 128 "##### Método `read(size)`\n", 129 "\n", 130 "Lee la cantidad de información del fichero indicada en el parámetro size. Si se omite, lee todo el contenido del fichero." 131 ] 132 }, 133 { 134 "cell_type": "markdown", 135 "metadata": { 136 "slideshow": { 137 "slide_type": "subslide" 138 } 139 }, 140 "source": [ 141 "##### Método `readline()`\n", 142 "\n", 143 "Cada vez que se llama, lee la siguiente linea del fichero, es decir, hasta el siguiente salto de línea.\n", 144 "\n", 145 "Para iterar sobre las líneas de un fichero, es más eficiente hacerlo directamente sobre el descriptor del fichero.\n", 146 "\n", 147 "```python\n", 148 ">>> for line in f:\n", 149 "... print(line, end='')\n", 150 "...\n", 151 "This is the first line of the file.\n", 152 "Second line of the file\n", 153 "```\n", 154 "\n", 155 "Puedes leer todas las lineas de un fichero y pasarlas a una lista con `list(f)` o `f.readlines()`." 156 ] 157 }, 158 { 159 "cell_type": "markdown", 160 "metadata": { 161 "slideshow": { 162 "slide_type": "slide" 163 } 164 }, 165 "source": [ 166 "#### Escritura de contenido" 167 ] 168 }, 169 { 170 "cell_type": "markdown", 171 "metadata": { 172 "slideshow": { 173 "slide_type": "subslide" 174 } 175 }, 176 "source": [ 177 "##### Método `write(string)`\n", 178 "\n", 179 "El método `write(string)` escribe el contenido de string en el fichero, devolviendo el número de caracteres escritos." 180 ] 181 }, 182 { 183 "cell_type": "markdown", 184 "metadata": { 185 "slideshow": { 186 "slide_type": "slide" 187 } 188 }, 189 "source": [ 190 "#### Moverse por el fichero\n", 191 "\n", 192 "El método `f.tell()` devuelve un entero con la posición en la que nos encontramos en el fichero, representado por el número de bytes desde el comienzo, cuando se abre en modo binario.\n", 193 "\n", 194 "Con el método `f.seek(offset, from_what)` nos podemos desplazar por el fichero. La posición a la que nos movemos se calcula añadiendo lo indicado en el offset a la posición refernciada en from_what, que es 0 para el comienzo del fichero, 1 para la posición actual del descriptor y 2 para el final del fichero.\n" 195 ] 196 }, 197 { 198 "cell_type": "markdown", 199 "metadata": { 200 "slideshow": { 201 "slide_type": "slide" 202 } 203 }, 204 "source": [ 205 "### Paquetes y módulos\n", 206 "\n", 207 "Cuando salimos del interprete y volvemos a entrar, todas las definiciones y declaraciones que hemos realizado se pierden. Para escribir cualquier programa que vaya más allá de lo que el uso puntual del interprete requiera, debemos escribirlo en un fichero de texto con la extensión `.py`." 208 ] 209 }, 210 { 211 "cell_type": "markdown", 212 "metadata": { 213 "slideshow": { 214 "slide_type": "slide" 215 } 216 }, 217 "source": [ 218 "El interprete de Python tratara cada uno de estos ficheros como un módulo, `module`. Cada definición de nombres, variables, funciones, etc. que contenga un módulo puede ser importado a otro módulo y ser usado en este." 219 ] 220 }, 221 { 222 "cell_type": "markdown", 223 "metadata": { 224 "slideshow": { 225 "slide_type": "slide" 226 } 227 }, 228 "source": [ 229 "Por ejemplo, si tenemos el siguiente fichero, `fibo.py`:" 230 ] 231 }, 232 { 233 "cell_type": "markdown", 234 "metadata": { 235 "slideshow": { 236 "slide_type": "fragment" 237 } 238 }, 239 "source": [ 240 "```python\n", 241 "# Módulo números de Fibonacci\n", 242 "\n", 243 "\n", 244 "def fib(n):\n", 245 " a, b = 0, 1\n", 246 " while b < n:\n", 247 " print(b, end=' ')\n", 248 " a, b = b, a+b\n", 249 " print()\n", 250 "\n", 251 " \n", 252 "def fib2(n):\n", 253 " result = []\n", 254 " a, b = 0, 1\n", 255 " while b < n:\n", 256 " result.append(b)\n", 257 " a, b = b, a+b\n", 258 " return result\n", 259 "```" 260 ] 261 }, 262 { 263 "cell_type": "markdown", 264 "metadata": { 265 "slideshow": { 266 "slide_type": "slide" 267 } 268 }, 269 "source": [ 270 "- Podemos importar estas funciones en el intérprete o en cualquier otro módulo.\n", 271 "- Cada módulo define una variable global `__name__`, que contiene el nombre del módulo.\n", 272 "\n", 273 "```python\n", 274 ">>> import fibo\n", 275 ">>> fibo.fib(1000)\n", 276 "1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987\n", 277 ">>> fibo.fib2(100)\n", 278 "[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]\n", 279 ">>> fibo.__name__\n", 280 "'fibo'\n", 281 "```" 282 ] 283 }, 284 { 285 "cell_type": "markdown", 286 "metadata": { 287 "slideshow": { 288 "slide_type": "slide" 289 } 290 }, 291 "source": [ 292 "Un módulo puede tener instrucciones además de definiciones. Estas instrucciones suelen tener como objetivo inicializar el módulo, y **sólo se ejecutarán la primera vez que se hace un `import` del módulo**. También se ejecutan cuando el fichero de módulo se ejecuta como un script." 293 ] 294 }, 295 { 296 "cell_type": "markdown", 297 "metadata": { 298 "slideshow": { 299 "slide_type": "slide" 300 } 301 }, 302 "source": [ 303 "Todo módulo tiene su propia tabla de símbolos, por lo que cualquiera puede usar variables globales sin preocuparse de que estas colisionen entre módulos.\n" 304 ] 305 }, 306 { 307 "cell_type": "markdown", 308 "metadata": { 309 "slideshow": { 310 "slide_type": "slide" 311 } 312 }, 313 "source": [ 314 "Se pueden importar nombres desde un módulo directamente a la tabla de nombres de otro módulo.\n", 315 "\n", 316 "```python\n", 317 ">>> from fibo import fib, fib2\n", 318 ">>> fib(500)\n", 319 "1 1 2 3 5 8 13 21 34 55 89 144 233 377\n", 320 "```" 321 ] 322 }, 323 { 324 "cell_type": "markdown", 325 "metadata": { 326 "slideshow": { 327 "slide_type": "slide" 328 } 329 }, 330 "source": [ 331 "Y también se pueden importar todos los nombres que define un módulo.\n", 332 "\n", 333 "```python\n", 334 ">>> from fibo import *\n", 335 ">>> fib(500)\n", 336 "1 1 2 3 5 8 13 21 34 55 89 144 233 377\n", 337 "```\n", 338 "\n", 339 "Esto importa todos los nombres excepto los que empiezan por `_`." 340 ] 341 }, 342 { 343 "cell_type": "markdown", 344 "metadata": { 345 "slideshow": { 346 "slide_type": "slide" 347 } 348 }, 349 "source": [ 350 "### Ejecutar módulos como scripts\n", 351 "\n", 352 "Puedes ejecutar cualquier módulo usando el comando de `python`.\n", 353 "\n", 354 "```\n", 355 "$ python fibo.py\n", 356 "```\n", 357 "\n", 358 "Si el código del módulo se ejecuta de esta forma, entonces la variable `__name__` del módulo toma el valor de `__main__`, lo que significa que podemos diferenciar que parte del modulo se ejecutará cuando se importa y cuando se ejecuta como script.\n", 359 "\n", 360 "```python\n", 361 "if __name__ == \"__main__\":\n", 362 " # Sólo ejecuta esto cuando es un script\n", 363 " pass \n", 364 "```" 365 ] 366 }, 367 { 368 "cell_type": "markdown", 369 "metadata": { 370 "slideshow": { 371 "slide_type": "slide" 372 } 373 }, 374 "source": [ 375 "### Paquetes\n", 376 "\n", 377 "Los paquetes o *packages* de Python son una forma de estructurar los módulos de Python. \n", 378 "\n", 379 "Se considera un package cualquier carpeta que tenga un fichero llamado `__init__.py`. Este fichero puede estar vacío, pero también puede incluir código para inicializar el paquete. Un paquete puede a su vez contener, o no, uno o varios módulos." 380 ] 381 }, 382 { 383 "cell_type": "markdown", 384 "metadata": { 385 "slideshow": { 386 "slide_type": "slide" 387 } 388 }, 389 "source": [ 390 "```\n", 391 "sound/ \n", 392 " __init__.py \n", 393 " formats/ \n", 394 " __init__.py\n", 395 " wavread.py\n", 396 " wavwrite.py\n", 397 " aiffread.py\n", 398 " aiffwrite.py\n", 399 " auread.py\n", 400 " auwrite.py\n", 401 " ...\n", 402 " effects/ \n", 403 " __init__.py\n", 404 " echo.py\n", 405 " surround.py\n", 406 " reverse.py\n", 407 " ...\n", 408 " filters/ \n", 409 " __init__.py\n", 410 " equalizer.py\n", 411 " vocoder.py\n", 412 " karaoke.py\n", 413 " ...\n", 414 "```" 415 ] 416 }, 417 { 418 "cell_type": "markdown", 419 "metadata": { 420 "slideshow": { 421 "slide_type": "slide" 422 } 423 }, 424 "source": [ 425 "Si se intenta hacer un `from sound.effects import *` cabría esperar que esto importara todos los nombres definidos en todos los módulos de dentro del paquete y sus sub-paquetes, pero sería muy costoso, por que se sigue la convención de que el autor de un paquete declare la variable `__all__` como una lista de nombres de los módulos que se importarán cuando se use el * para importar todo." 426 ] 427 } 428 ], 429 "metadata": { 430 "celltoolbar": "Slideshow", 431 "kernelspec": { 432 "display_name": "Python 3", 433 "language": "python", 434 "name": "python3" 435 }, 436 "language_info": { 437 "codemirror_mode": { 438 "name": "ipython", 439 "version": 3 440 }, 441 "file_extension": ".py", 442 "mimetype": "text/x-python", 443 "name": "python", 444 "nbconvert_exporter": "python", 445 "pygments_lexer": "ipython3", 446 "version": "3.7.1" 447 } 448 }, 449 "nbformat": 4, 450 "nbformat_minor": 2 451}