From e4093571b0827a4b7ca588475b66a60635da9954 Mon Sep 17 00:00:00 2001 From: Ramon Rodriguez Date: Wed, 19 Aug 2026 06:43:52 -0300 Subject: [PATCH] Add open and with chapter --- README.md | 2 +- docs/learning-path.en.md | 3 +- docs/learning-path.es.md | 3 +- docs/learning-path.pt-BR.md | 3 +- docs/localized/README.es.md | 2 +- docs/localized/README.pt-BR.md | 2 +- docs/project-structure.en.md | 18 +- docs/project-structure.es.md | 18 +- docs/project-structure.pt-BR.md | 18 +- docs/roadmap.en.md | 6 +- docs/roadmap.es.md | 6 +- docs/roadmap.pt-BR.md | 6 +- .../03-open-and-with/README.es.md | 847 ++++++++++++++++++ .../03-open-and-with/README.md | 847 ++++++++++++++++++ .../03-open-and-with/README.pt-BR.md | 847 ++++++++++++++++++ .../03-open-and-with/examples/append_text.py | 16 + .../examples/handle_missing_file.py | 14 + .../examples/write_and_read_text.py | 15 + errors-files-and-modules/README.es.md | 22 +- errors-files-and-modules/README.md | 22 +- errors-files-and-modules/README.pt-BR.md | 22 +- scripts/example_manifest.txt | 3 + 22 files changed, 2691 insertions(+), 51 deletions(-) create mode 100644 errors-files-and-modules/03-open-and-with/README.es.md create mode 100644 errors-files-and-modules/03-open-and-with/README.md create mode 100644 errors-files-and-modules/03-open-and-with/README.pt-BR.md create mode 100644 errors-files-and-modules/03-open-and-with/examples/append_text.py create mode 100644 errors-files-and-modules/03-open-and-with/examples/handle_missing_file.py create mode 100644 errors-files-and-modules/03-open-and-with/examples/write_and_read_text.py diff --git a/README.md b/README.md index 3cd3689..bb203ce 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ The project foundation and six complete educational sections are available, and - [Comments versus Logging in Python](comments-and-documentation/05-comments-vs-logging/README.md) - [PEP 8 and Readability in Python](comments-and-documentation/06-pep8-and-readability/README.md) -Phases 1, 2, 3, 4, 5, and 6 are complete. Phase 7 now includes [Handling Exceptions with `try`, `except`, `else`, and `finally`](errors-files-and-modules/01-try-except-else-finally/README.md), which establishes specific handlers, success-only `else`, cleanup-oriented `finally`, propagation, and narrow failure boundaries, plus [Raising and Custom Exceptions](errors-files-and-modules/02-raise-and-custom-exceptions/README.md), which adds deliberate `raise`, built-in and custom exception selection, re-raising, explicit chaining, and the distinction between `raise` and `assert`. Phase 5: Functions contains nine reviewed chapters: [Defining and Calling Functions](functions/01-defining-and-calling-functions/README.md), [Parameters and Arguments](functions/02-parameters-and-arguments/README.md), [Return Values](functions/03-return-values/README.md), [Scope](functions/04-scope/README.md), [Type Hints](functions/05-type-hints/README.md), [Default Values](functions/06-default-values/README.md), [`*args` and `**kwargs`](functions/07-args-and-kwargs/README.md), [Functions Working Together](functions/08-functions-working-together/README.md), and [Data Flow Between Functions](functions/09-data-flow-between-functions/README.md). Together they establish function definition and calling, required input flow, returned results, local and global scope, typed interfaces, safe optional inputs, intentionally flexible positional and keyword argument collection, composition through helpers and coordinators, and explicit caller-to-parameter-to-return data flow including rebinding versus mutation. Phase 4 remains complete with eight reviewed Program Flow chapters, ending with [Choosing and Combining Program Flow](program-flow/08-choosing-and-combining-program-flow/README.md). Phase 3 contains six reviewed Collections chapters, ending with [Choosing the Right Collection](collections/06-choosing-the-right-collection/README.md). Phase 2 remains complete with four reviewed chapters, ending with [Numeric Built-ins](strings-and-numbers/04-numeric-builtins/README.md). See the [roadmap](docs/roadmap.en.md) or the [full learning path](docs/learning-path.en.md) for the current curriculum status and direct chapter links. +Phases 1, 2, 3, 4, 5, and 6 are complete. Phase 7 now includes three reviewed chapters: exception handling; deliberate raising and custom exceptions; and [Opening Files Safely with `open()` and `with`](errors-files-and-modules/03-open-and-with/README.md), which introduces text-file modes, explicit encodings, reading, writing, appending, focused file errors, and context-managed cleanup. Phase 5: Functions contains nine reviewed chapters: [Defining and Calling Functions](functions/01-defining-and-calling-functions/README.md), [Parameters and Arguments](functions/02-parameters-and-arguments/README.md), [Return Values](functions/03-return-values/README.md), [Scope](functions/04-scope/README.md), [Type Hints](functions/05-type-hints/README.md), [Default Values](functions/06-default-values/README.md), [`*args` and `**kwargs`](functions/07-args-and-kwargs/README.md), [Functions Working Together](functions/08-functions-working-together/README.md), and [Data Flow Between Functions](functions/09-data-flow-between-functions/README.md). Together they establish function definition and calling, required input flow, returned results, local and global scope, typed interfaces, safe optional inputs, intentionally flexible positional and keyword argument collection, composition through helpers and coordinators, and explicit caller-to-parameter-to-return data flow including rebinding versus mutation. Phase 4 remains complete with eight reviewed Program Flow chapters, ending with [Choosing and Combining Program Flow](program-flow/08-choosing-and-combining-program-flow/README.md). Phase 3 contains six reviewed Collections chapters, ending with [Choosing the Right Collection](collections/06-choosing-the-right-collection/README.md). Phase 2 remains complete with four reviewed chapters, ending with [Numeric Built-ins](strings-and-numbers/04-numeric-builtins/README.md). See the [roadmap](docs/roadmap.en.md) or the [full learning path](docs/learning-path.en.md) for the current curriculum status and direct chapter links. ## Visual identity diff --git a/docs/learning-path.en.md b/docs/learning-path.en.md index b58d8f3..b3913ad 100644 --- a/docs/learning-path.en.md +++ b/docs/learning-path.en.md @@ -93,8 +93,9 @@ This phase is already available and is the next recommended phase after Function 1. [Handling Exceptions with `try`, `except`, `else`, and `finally`](../errors-files-and-modules/01-try-except-else-finally/README.md) 2. [Raising and Custom Exceptions](../errors-files-and-modules/02-raise-and-custom-exceptions/README.md) +3. [Opening Files Safely with `open()` and `with`](../errors-files-and-modules/03-open-and-with/README.md) -Phase 7 is in progress. Chapter 01 establishes the runtime-exception and handler model. Chapter 02 adds deliberate `raise`, built-in versus custom exception selection, bare re-raising, explicit chaining with `from`, and the distinction between `raise` and `assert`. The next planned chapter is **`open()` and `with`**. +Phase 7 is in progress. Chapters 01–02 establish exception handling and deliberate signaling. Chapter 03 adds text-file modes, explicit encodings, reading, writing, appending, file exceptions, and context-managed cleanup. The next planned chapter is **TXT, CSV, and JSON**. ## Phase 8 · Standard Library ⏳ diff --git a/docs/learning-path.es.md b/docs/learning-path.es.md index 9d4cc33..b6bb74e 100644 --- a/docs/learning-path.es.md +++ b/docs/learning-path.es.md @@ -93,8 +93,9 @@ Esta fase ya está disponible y es la siguiente fase recomendada después de Fun 1. [Manejo de Excepciones con `try`, `except`, `else` y `finally`](../errors-files-and-modules/01-try-except-else-finally/README.es.md) 2. [Lanzar Excepciones y Crear Excepciones Personalizadas](../errors-files-and-modules/02-raise-and-custom-exceptions/README.es.md) +3. [Abrir Archivos de Forma Segura con `open()` y `with`](../errors-files-and-modules/03-open-and-with/README.es.md) -La Fase 7 está en progreso. El Capítulo 01 establece el modelo de excepciones en runtime y handlers. El Capítulo 02 añade `raise` deliberado, elección entre excepciones built-in y personalizadas, relanzamiento con `raise` sin expresión, encadenamiento explícito con `from` y la distinción entre `raise` y `assert`. El próximo capítulo planificado es **`open()` y `with`**. +La Fase 7 está en progreso. Los Capítulos 01–02 establecen manejo y señalización deliberada de excepciones. El Capítulo 03 añade modos de archivo de texto, encoding explícito, lectura, escritura, append, excepciones de archivo y limpieza gestionada por contexto. El próximo capítulo planificado es **TXT, CSV y JSON**. ## Fase 8 · Biblioteca Estándar ⏳ diff --git a/docs/learning-path.pt-BR.md b/docs/learning-path.pt-BR.md index 85d56ec..f8f1cf4 100644 --- a/docs/learning-path.pt-BR.md +++ b/docs/learning-path.pt-BR.md @@ -93,8 +93,9 @@ Esta fase já está disponível e é a próxima fase recomendada depois de Funç 1. [Tratando Exceções com `try`, `except`, `else` e `finally`](../errors-files-and-modules/01-try-except-else-finally/README.pt-BR.md) 2. [Levantando Exceções e Criando Exceções Personalizadas](../errors-files-and-modules/02-raise-and-custom-exceptions/README.pt-BR.md) +3. [Abrindo Arquivos com Segurança com `open()` e `with`](../errors-files-and-modules/03-open-and-with/README.pt-BR.md) -A Fase 7 está em andamento. O Capítulo 01 estabelece o modelo de exceções em runtime e handlers. O Capítulo 02 acrescenta `raise` deliberado, escolha entre exceções built-in e personalizadas, relançamento com `raise` sem expressão, encadeamento explícito com `from` e a distinção entre `raise` e `assert`. O próximo capítulo planejado é **`open()` e `with`**. +A Fase 7 está em andamento. Os Capítulos 01–02 estabelecem tratamento e sinalização deliberada de exceções. O Capítulo 03 acrescenta modos de arquivo de texto, encoding explícito, leitura, escrita, append, exceções de arquivo e limpeza gerenciada por contexto. O próximo capítulo planejado é **TXT, CSV e JSON**. ## Fase 8 · Biblioteca Padrão ⏳ diff --git a/docs/localized/README.es.md b/docs/localized/README.es.md index e38ef54..226646c 100644 --- a/docs/localized/README.es.md +++ b/docs/localized/README.es.md @@ -85,7 +85,7 @@ La base del proyecto y seis secciones educativas completas están disponibles, y - [Comentarios frente a Logging en Python](../../comments-and-documentation/05-comments-vs-logging/README.es.md) - [PEP 8 y Legibilidad en Python](../../comments-and-documentation/06-pep8-and-readability/README.es.md) -Las Fases 1, 2, 3, 4, 5 y 6 están completadas. La Fase 7 ahora incluye [Manejo de Excepciones con `try`, `except`, `else` y `finally`](../../errors-files-and-modules/01-try-except-else-finally/README.es.md), que establece handlers específicos, ruta de éxito con `else`, limpieza con `finally`, propagación y límites de fallo pequeños, además de [Lanzar Excepciones y Crear Excepciones Personalizadas](../../errors-files-and-modules/02-raise-and-custom-exceptions/README.es.md), que añade `raise` deliberado, elección entre excepciones built-in y personalizadas, relanzamiento, encadenamiento explícito y la distinción entre `raise` y `assert`. La Fase 5: Funciones reúne nueve capítulos revisados: [Definir y Llamar Funciones](../../functions/01-defining-and-calling-functions/README.es.md), [Parámetros y Argumentos](../../functions/02-parameters-and-arguments/README.es.md), [Valores de Retorno](../../functions/03-return-values/README.es.md), [Alcance](../../functions/04-scope/README.es.md), [Type Hints](../../functions/05-type-hints/README.es.md), [Valores Predeterminados](../../functions/06-default-values/README.es.md), [`*args` y `**kwargs`](../../functions/07-args-and-kwargs/README.es.md), [Funciones Trabajando Juntas](../../functions/08-functions-working-together/README.es.md) y [Flujo de Datos Entre Funciones](../../functions/09-data-flow-between-functions/README.es.md). Juntos establecen definición y llamada, flujo de entrada obligatorio, resultados retornados, alcance local y global, interfaces tipadas, entradas opcionales seguras, recolección intencionalmente flexible de argumentos posicionales y por palabra clave, composición mediante funciones auxiliares y coordinadoras y flujo explícito desde el llamador hacia parámetros y retornos, incluida la reasignación frente a la mutación. La Fase 4 permanece completada con ocho capítulos revisados de Flujo del Programa, terminando con [Elegir y Combinar el Flujo del Programa](../../program-flow/08-choosing-and-combining-program-flow/README.es.md). La Fase 3 reúne seis capítulos revisados de Colecciones, terminando con [Elegir la Colección Adecuada](../../collections/06-choosing-the-right-collection/README.es.md). La Fase 2 permanece completada con cuatro capítulos revisados, terminando con [Funciones Numéricas Incorporadas](../../strings-and-numbers/04-numeric-builtins/README.es.md). Consulta el [roadmap](../roadmap.es.md) o la [ruta completa de aprendizaje](../learning-path.es.md) para seguir el estado del currículo y acceder directamente a los capítulos. +Las Fases 1, 2, 3, 4, 5 y 6 están completadas. La Fase 7 ahora incluye tres capítulos revisados: manejo de excepciones; lanzamiento y excepciones personalizadas; y [Abrir Archivos de Forma Segura con `open()` y `with`](../../errors-files-and-modules/03-open-and-with/README.es.md), que introduce modos de archivo de texto, encoding explícito, lectura, escritura, append, errores de archivo específicos y limpieza gestionada por contexto. La Fase 5: Funciones reúne nueve capítulos revisados: [Definir y Llamar Funciones](../../functions/01-defining-and-calling-functions/README.es.md), [Parámetros y Argumentos](../../functions/02-parameters-and-arguments/README.es.md), [Valores de Retorno](../../functions/03-return-values/README.es.md), [Alcance](../../functions/04-scope/README.es.md), [Type Hints](../../functions/05-type-hints/README.es.md), [Valores Predeterminados](../../functions/06-default-values/README.es.md), [`*args` y `**kwargs`](../../functions/07-args-and-kwargs/README.es.md), [Funciones Trabajando Juntas](../../functions/08-functions-working-together/README.es.md) y [Flujo de Datos Entre Funciones](../../functions/09-data-flow-between-functions/README.es.md). Juntos establecen definición y llamada, flujo de entrada obligatorio, resultados retornados, alcance local y global, interfaces tipadas, entradas opcionales seguras, recolección intencionalmente flexible de argumentos posicionales y por palabra clave, composición mediante funciones auxiliares y coordinadoras y flujo explícito desde el llamador hacia parámetros y retornos, incluida la reasignación frente a la mutación. La Fase 4 permanece completada con ocho capítulos revisados de Flujo del Programa, terminando con [Elegir y Combinar el Flujo del Programa](../../program-flow/08-choosing-and-combining-program-flow/README.es.md). La Fase 3 reúne seis capítulos revisados de Colecciones, terminando con [Elegir la Colección Adecuada](../../collections/06-choosing-the-right-collection/README.es.md). La Fase 2 permanece completada con cuatro capítulos revisados, terminando con [Funciones Numéricas Incorporadas](../../strings-and-numbers/04-numeric-builtins/README.es.md). Consulta el [roadmap](../roadmap.es.md) o la [ruta completa de aprendizaje](../learning-path.es.md) para seguir el estado del currículo y acceder directamente a los capítulos. ## Identidad visual diff --git a/docs/localized/README.pt-BR.md b/docs/localized/README.pt-BR.md index 0535a2a..5f1e4f6 100644 --- a/docs/localized/README.pt-BR.md +++ b/docs/localized/README.pt-BR.md @@ -85,7 +85,7 @@ A fundação do projeto e seis seções educacionais completas estão disponíve - [Comentários versus Logging em Python](../../comments-and-documentation/05-comments-vs-logging/README.pt-BR.md) - [PEP 8 e Legibilidade em Python](../../comments-and-documentation/06-pep8-and-readability/README.pt-BR.md) -As Fases 1, 2, 3, 4, 5 e 6 estão concluídas. A Fase 7 agora inclui [Tratando Exceções com `try`, `except`, `else` e `finally`](../../errors-files-and-modules/01-try-except-else-finally/README.pt-BR.md), que estabelece handlers específicos, caminho de sucesso com `else`, limpeza com `finally`, propagação e fronteiras de falha estreitas, além de [Levantando Exceções e Criando Exceções Personalizadas](../../errors-files-and-modules/02-raise-and-custom-exceptions/README.pt-BR.md), que acrescenta `raise` deliberado, escolha entre exceções built-in e personalizadas, relançamento, encadeamento explícito e a distinção entre `raise` e `assert`. A Fase 5: Funções reúne nove capítulos revisados: [Definindo e Chamando Funções](../../functions/01-defining-and-calling-functions/README.pt-BR.md), [Parâmetros e Argumentos](../../functions/02-parameters-and-arguments/README.pt-BR.md), [Valores de Retorno](../../functions/03-return-values/README.pt-BR.md), [Escopo](../../functions/04-scope/README.pt-BR.md), [Type Hints](../../functions/05-type-hints/README.pt-BR.md), [Valores Padrão](../../functions/06-default-values/README.pt-BR.md), [`*args` e `**kwargs`](../../functions/07-args-and-kwargs/README.pt-BR.md), [Funções Trabalhando Juntas](../../functions/08-functions-working-together/README.pt-BR.md) e [Fluxo de Dados Entre Funções](../../functions/09-data-flow-between-functions/README.pt-BR.md). Juntos, eles estabelecem definição e chamada, fluxo de entrada obrigatório, resultados retornados, escopo local e global, interfaces tipadas, entradas opcionais seguras, coleta intencionalmente flexível de argumentos posicionais e nomeados, composição por funções auxiliares e coordenadoras e fluxo explícito do chamador aos parâmetros e retornos, incluindo reatribuição versus mutação. A Fase 4 permanece concluída com oito capítulos revisados de Fluxo do Programa, encerrando com [Escolhendo e Combinando o Fluxo do Programa](../../program-flow/08-choosing-and-combining-program-flow/README.pt-BR.md). A Fase 3 reúne seis capítulos revisados de Coleções, encerrando com [Escolhendo a Coleção Certa](../../collections/06-choosing-the-right-collection/README.pt-BR.md). A Fase 2 permanece concluída com quatro capítulos revisados, encerrando com [Funções Numéricas Embutidas](../../strings-and-numbers/04-numeric-builtins/README.pt-BR.md). Consulte o [roadmap](../roadmap.pt-BR.md) ou a [trilha completa de estudos](../learning-path.pt-BR.md) para acompanhar o status do currículo e acessar os capítulos diretamente. +As Fases 1, 2, 3, 4, 5 e 6 estão concluídas. A Fase 7 agora inclui três capítulos revisados: tratamento de exceções; levantamento e exceções personalizadas; e [Abrindo Arquivos com Segurança com `open()` e `with`](../../errors-files-and-modules/03-open-and-with/README.pt-BR.md), que introduz modos de arquivo de texto, encoding explícito, leitura, escrita, append, erros de arquivo específicos e limpeza gerenciada por contexto. A Fase 5: Funções reúne nove capítulos revisados: [Definindo e Chamando Funções](../../functions/01-defining-and-calling-functions/README.pt-BR.md), [Parâmetros e Argumentos](../../functions/02-parameters-and-arguments/README.pt-BR.md), [Valores de Retorno](../../functions/03-return-values/README.pt-BR.md), [Escopo](../../functions/04-scope/README.pt-BR.md), [Type Hints](../../functions/05-type-hints/README.pt-BR.md), [Valores Padrão](../../functions/06-default-values/README.pt-BR.md), [`*args` e `**kwargs`](../../functions/07-args-and-kwargs/README.pt-BR.md), [Funções Trabalhando Juntas](../../functions/08-functions-working-together/README.pt-BR.md) e [Fluxo de Dados Entre Funções](../../functions/09-data-flow-between-functions/README.pt-BR.md). Juntos, eles estabelecem definição e chamada, fluxo de entrada obrigatório, resultados retornados, escopo local e global, interfaces tipadas, entradas opcionais seguras, coleta intencionalmente flexível de argumentos posicionais e nomeados, composição por funções auxiliares e coordenadoras e fluxo explícito do chamador aos parâmetros e retornos, incluindo reatribuição versus mutação. A Fase 4 permanece concluída com oito capítulos revisados de Fluxo do Programa, encerrando com [Escolhendo e Combinando o Fluxo do Programa](../../program-flow/08-choosing-and-combining-program-flow/README.pt-BR.md). A Fase 3 reúne seis capítulos revisados de Coleções, encerrando com [Escolhendo a Coleção Certa](../../collections/06-choosing-the-right-collection/README.pt-BR.md). A Fase 2 permanece concluída com quatro capítulos revisados, encerrando com [Funções Numéricas Embutidas](../../strings-and-numbers/04-numeric-builtins/README.pt-BR.md). Consulte o [roadmap](../roadmap.pt-BR.md) ou a [trilha completa de estudos](../learning-path.pt-BR.md) para acompanhar o status do currículo e acessar os capítulos diretamente. ## Identidade visual diff --git a/docs/project-structure.en.md b/docs/project-structure.en.md index 795d291..41c14b3 100644 --- a/docs/project-structure.en.md +++ b/docs/project-structure.en.md @@ -149,14 +149,22 @@ python-study-guide/ │ │ ├── parse_integer.py │ │ ├── safe_divide.py │ │ └── trace_try_else_finally.py -│ └── 02-raise-and-custom-exceptions/ +│ ├── 02-raise-and-custom-exceptions/ +│ │ ├── README.md +│ │ ├── README.pt-BR.md +│ │ ├── README.es.md +│ │ └── examples/ +│ │ ├── custom_exception.py +│ │ ├── exception_chaining.py +│ │ └── validate_score.py +│ └── 03-open-and-with/ │ ├── README.md │ ├── README.pt-BR.md │ ├── README.es.md │ └── examples/ -│ ├── custom_exception.py -│ ├── exception_chaining.py -│ └── validate_score.py +│ ├── append_text.py +│ ├── handle_missing_file.py +│ └── write_and_read_text.py ├── exercises/ ├── external-libraries/ ├── functions/ @@ -408,7 +416,7 @@ python-study-guide/ - `comments-and-documentation/`: complete Phase 6 learning path. Reviewed chapters are available for comments, docstrings, meaningful names, task markers, comments versus logging, and PEP 8 and readability, each in English, Brazilian Portuguese, and Spanish with safe executable examples. - `collections/`: complete Phase 3 learning path. Its six chapters teach list creation, reading, mutation, common methods, shallow copying, tuples and immutability, dictionary key-value mappings and views, set uniqueness and relationships, and how to choose among lists, tuples, dictionaries, and sets by intent, in English, Brazilian Portuguese, and Spanish with safe executable examples. - `docs/`: master learning paths, roadmaps, project architecture, localized project documents, policies, and responsible AI-assisted development guidance. -- `errors-files-and-modules/`: in-progress Phase 7 learning path. Chapters 01–02 cover specific exception handling, `else`, `finally`, propagation, deliberate `raise`, built-in versus custom exception selection, bare re-raising, explicit exception chaining, `raise` versus `assert`, and deterministic executable examples in English, Brazilian Portuguese, and Spanish. +- `errors-files-and-modules/`: in-progress Phase 7 learning path. Chapters 01–03 cover runtime exception handling, deliberate raising and custom exceptions, and safe text-file I/O with `open()`, explicit encodings, file modes, focused file exceptions, and `with`, in English, Brazilian Portuguese, and Spanish with deterministic executable examples. - `exercises/`: focused practice activities connected to learning chapters. - `external-libraries/`: future guides to third-party packages. - `functions/`: complete Phase 5 learning path. Chapters 01–09 cover defining and calling functions, required inputs, returned values, scope and name lookup, type hints for function interfaces, default values including definition-time evaluation and mutable-default safety, variable-length positional and keyword argument collection with `*args` and `**kwargs`, composition through helper and coordinating functions with explicit dependencies and simple call graphs, and explicit data-flow tracing across calls including parameter bindings, rebinding versus mutation, `None`, tuple results, and return-based handoffs, in English, Brazilian Portuguese, and Spanish with deterministic executable examples. diff --git a/docs/project-structure.es.md b/docs/project-structure.es.md index d35bdc3..924f577 100644 --- a/docs/project-structure.es.md +++ b/docs/project-structure.es.md @@ -149,14 +149,22 @@ python-study-guide/ │ │ ├── parse_integer.py │ │ ├── safe_divide.py │ │ └── trace_try_else_finally.py -│ └── 02-raise-and-custom-exceptions/ +│ ├── 02-raise-and-custom-exceptions/ +│ │ ├── README.md +│ │ ├── README.pt-BR.md +│ │ ├── README.es.md +│ │ └── examples/ +│ │ ├── custom_exception.py +│ │ ├── exception_chaining.py +│ │ └── validate_score.py +│ └── 03-open-and-with/ │ ├── README.md │ ├── README.pt-BR.md │ ├── README.es.md │ └── examples/ -│ ├── custom_exception.py -│ ├── exception_chaining.py -│ └── validate_score.py +│ ├── append_text.py +│ ├── handle_missing_file.py +│ └── write_and_read_text.py ├── exercises/ ├── external-libraries/ ├── functions/ @@ -408,7 +416,7 @@ python-study-guide/ - `comments-and-documentation/`: ruta completa de la Fase 6. Hay capítulos revisados sobre comentarios, docstrings, nombres significativos, marcadores de tareas, comentarios frente a logging y PEP 8 y legibilidad, cada uno en inglés, portugués de Brasil y español, con ejemplos ejecutables seguros. - `collections/`: ruta completa de la Fase 3. Sus seis capítulos enseñan creación, lectura, mutación y métodos comunes de listas, copia superficial, tuplas e inmutabilidad, mappings clave-valor y vistas de diccionarios, unicidad y relaciones de conjuntos y cómo elegir entre listas, tuplas, diccionarios y conjuntos según la intención, en inglés, portugués de Brasil y español, con ejemplos ejecutables seguros. - `docs/`: rutas completas de aprendizaje, roadmaps, arquitectura del proyecto, documentos localizados, políticas y guía de desarrollo responsable asistido por IA. -- `errors-files-and-modules/`: ruta en progreso de la Fase 7. Los Capítulos 01–02 cubren manejo específico de excepciones, `else`, `finally`, propagación, `raise` deliberado, elección entre excepciones built-in y personalizadas, relanzamiento con `raise` sin expresión, encadenamiento explícito, `raise` frente a `assert` y ejemplos ejecutables determinísticos en inglés, portugués de Brasil y español. +- `errors-files-and-modules/`: ruta en progreso de la Fase 7. Los Capítulos 01–03 cubren manejo de excepciones de runtime, lanzamiento y excepciones personalizadas e I/O seguro de archivos de texto con `open()`, encoding explícito, modos de archivo, excepciones de archivo específicas y `with`, en inglés, portugués de Brasil y español con ejemplos ejecutables determinísticos. - `exercises/`: actividades prácticas relacionadas con los capítulos. - `external-libraries/`: futuras guías sobre paquetes de terceros. - `functions/`: ruta completa de la Fase 5. Los Capítulos 01–09 cubren definición y llamada de funciones, entradas obligatorias, valores retornados, alcance y búsqueda de nombres, type hints para interfaces de funciones, valores predeterminados incluida la evaluación al definir la función y la seguridad con valores mutables, recolección de argumentos posicionales y por palabra clave de cantidad variable con `*args` y `**kwargs`, composición mediante funciones auxiliares y coordinadoras con dependencias explícitas y grafos simples de llamadas, y seguimiento explícito del flujo de datos entre llamadas, incluidos vínculos de parámetros, reasignación frente a mutación, `None`, resultados en tupla y traspasos mediante `return`, en inglés, portugués de Brasil y español, con ejemplos ejecutables determinísticos. diff --git a/docs/project-structure.pt-BR.md b/docs/project-structure.pt-BR.md index 429f872..272aaf3 100644 --- a/docs/project-structure.pt-BR.md +++ b/docs/project-structure.pt-BR.md @@ -149,14 +149,22 @@ python-study-guide/ │ │ ├── parse_integer.py │ │ ├── safe_divide.py │ │ └── trace_try_else_finally.py -│ └── 02-raise-and-custom-exceptions/ +│ ├── 02-raise-and-custom-exceptions/ +│ │ ├── README.md +│ │ ├── README.pt-BR.md +│ │ ├── README.es.md +│ │ └── examples/ +│ │ ├── custom_exception.py +│ │ ├── exception_chaining.py +│ │ └── validate_score.py +│ └── 03-open-and-with/ │ ├── README.md │ ├── README.pt-BR.md │ ├── README.es.md │ └── examples/ -│ ├── custom_exception.py -│ ├── exception_chaining.py -│ └── validate_score.py +│ ├── append_text.py +│ ├── handle_missing_file.py +│ └── write_and_read_text.py ├── exercises/ ├── external-libraries/ ├── functions/ @@ -408,7 +416,7 @@ python-study-guide/ - `comments-and-documentation/`: trilha completa da Fase 6. Há capítulos revisados sobre comentários, docstrings, nomes significativos, marcadores de tarefas, comentários versus logging e PEP 8 e legibilidade, cada um em inglês, português brasileiro e espanhol, com exemplos executáveis seguros. - `collections/`: trilha completa da Fase 3. Seus seis capítulos ensinam criação, leitura, mutação e métodos comuns de listas, cópia rasa, tuplas e imutabilidade, mapeamentos chave-valor e views de dicionários, unicidade e relações de conjuntos e como escolher entre listas, tuplas, dicionários e conjuntos de acordo com a intenção, em inglês, português brasileiro e espanhol, com exemplos executáveis seguros. - `docs/`: trilhas completas de estudos, roadmaps, arquitetura do projeto, documentos localizados, políticas e guia de desenvolvimento responsável assistido por IA. -- `errors-files-and-modules/`: trilha em andamento da Fase 7. Os Capítulos 01–02 cobrem tratamento específico de exceções, `else`, `finally`, propagação, `raise` deliberado, escolha entre exceções built-in e personalizadas, relançamento com `raise` sem expressão, encadeamento explícito, `raise` versus `assert` e exemplos executáveis determinísticos em inglês, português brasileiro e espanhol. +- `errors-files-and-modules/`: trilha em andamento da Fase 7. Os Capítulos 01–03 cobrem tratamento de exceções de runtime, levantamento e exceções personalizadas e I/O seguro de arquivos de texto com `open()`, encoding explícito, modos de arquivo, exceções de arquivo específicas e `with`, em inglês, português brasileiro e espanhol com exemplos executáveis determinísticos. - `exercises/`: atividades práticas relacionadas aos capítulos. - `external-libraries/`: futuros guias sobre pacotes de terceiros. - `functions/`: trilha completa da Fase 5. Os Capítulos 01–09 cobrem definição e chamada de funções, entradas obrigatórias, valores retornados, escopo e busca de nomes, type hints para interfaces de funções, valores padrão incluindo avaliação no momento da definição e segurança com padrões mutáveis, coleta de argumentos posicionais e nomeados de quantidade variável com `*args` e `**kwargs`, composição por funções auxiliares e coordenadoras com dependências explícitas e grafos simples de chamadas e rastreamento explícito do fluxo de dados entre chamadas, incluindo vínculos de parâmetros, reatribuição versus mutação, `None`, resultados em tupla e passagens por `return`, em inglês, português brasileiro e espanhol com exemplos executáveis determinísticos. diff --git a/docs/roadmap.en.md b/docs/roadmap.en.md index 963cac1..19d7b92 100644 --- a/docs/roadmap.en.md +++ b/docs/roadmap.en.md @@ -21,7 +21,7 @@ This roadmap tracks both the educational curriculum and the repository foundatio | 4. Program flow | Complete | Eight reviewed chapters cover conditions, branching, structural pattern matching, `for`, iteration helpers, `while`, loop control, and choosing and combining flow tools by intent | | 5. Functions | Complete | Nine reviewed chapters cover `def`, calls, required inputs, returned values, scope, type hints, safe defaults, flexible arguments, function composition, and explicit data flow | | 6. Comments, documentation, and clean code | Complete | Six reviewed chapters are available and the pilot educational section is officially complete | -| 7. Errors, files, and modules | In progress | Chapters 01–02 cover handling runtime exceptions and deliberately raising, re-raising, chaining, and defining custom exceptions | +| 7. Errors, files, and modules | In progress | Chapters 01–03 cover exception handling, deliberate exception signaling, and safe text-file I/O with `open()` and `with` | | 8. Standard library | Planned | Curriculum not started | | 9. External libraries | Planned | Curriculum not started | | 10. Practical projects | Planned | Curriculum not started | @@ -130,11 +130,11 @@ See the [section learning path](../errors-files-and-modules/README.md). - [x] [`try`, `except`, `else`, and `finally`](../errors-files-and-modules/01-try-except-else-finally/README.md) - [x] [`raise` and custom exceptions](../errors-files-and-modules/02-raise-and-custom-exceptions/README.md) -- [ ] `open()` and `with` +- [x] [`open()` and `with`](../errors-files-and-modules/03-open-and-with/README.md) - [ ] TXT, CSV, and JSON - [ ] Imports, modules, and packages -Phase 7 is in progress. Chapter 01 establishes runtime exception handling, specific handlers, `else`, `finally`, propagation, and narrow failure boundaries. Chapter 02 adds deliberate `raise`, choosing built-in versus custom exception types, bare re-raising, explicit chaining, and `raise` versus `assert`. The next planned chapter is **`open()` and `with`**. +Phase 7 is in progress. Chapters 01–02 establish exception handling and deliberate signaling. Chapter 03 adds safe text-file I/O with modes, explicit encodings, reading, writing, appending, focused file exceptions, and `with`. The next planned chapter is **TXT, CSV, and JSON**. ## Phase 8: Standard library diff --git a/docs/roadmap.es.md b/docs/roadmap.es.md index ff8390c..c67cb1f 100644 --- a/docs/roadmap.es.md +++ b/docs/roadmap.es.md @@ -21,7 +21,7 @@ Este roadmap acompaña tanto la ruta educativa como la base del repositorio que | 4. Flujo del programa | Completada | Ocho capítulos revisados cubren condiciones, ramificaciones, coincidencia de patrones estructurales, `for`, ayudas de iteración, `while`, control de bucles y elección y combinación de herramientas de flujo según la intención | | 5. Funciones | Completada | Nueve capítulos revisados cubren `def`, llamadas, entradas obligatorias, valores retornados, alcance, type hints, valores predeterminados seguros, argumentos flexibles, composición de funciones y flujo explícito de datos | | 6. Comentarios, documentación y código limpio | Completada | Seis capítulos revisados están disponibles y la sección educativa piloto está oficialmente completada | -| 7. Errores, archivos y módulos | En progreso | Los Capítulos 01–02 cubren manejo de excepciones de runtime y generación, relanzamiento, encadenamiento y definición deliberada de excepciones personalizadas | +| 7. Errores, archivos y módulos | En progreso | Los Capítulos 01–03 cubren manejo de excepciones, señalización deliberada e I/O seguro de archivos de texto con `open()` y `with` | | 8. Biblioteca estándar | Planificada | Contenido todavía no iniciado | | 9. Bibliotecas externas | Planificada | Contenido todavía no iniciado | | 10. Proyectos prácticos | Planificada | Contenido todavía no iniciado | @@ -130,11 +130,11 @@ Consulta la [ruta de aprendizaje de la sección](../errors-files-and-modules/REA - [x] [`try`, `except`, `else` y `finally`](../errors-files-and-modules/01-try-except-else-finally/README.es.md) - [x] [`raise` y excepciones personalizadas](../errors-files-and-modules/02-raise-and-custom-exceptions/README.es.md) -- [ ] `open()` y `with` +- [x] [`open()` y `with`](../errors-files-and-modules/03-open-and-with/README.es.md) - [ ] TXT, CSV y JSON - [ ] Imports, módulos y paquetes -La Fase 7 está en progreso. El Capítulo 01 establece manejo de excepciones de runtime, handlers específicos, `else`, `finally`, propagación y límites de fallo pequeños. El Capítulo 02 añade `raise` deliberado, elección entre excepciones built-in y personalizadas, relanzamiento con `raise` sin expresión, encadenamiento explícito y `raise` frente a `assert`. El próximo capítulo planificado es **`open()` y `with`**. +La Fase 7 está en progreso. Los Capítulos 01–02 establecen manejo y señalización deliberada de excepciones. El Capítulo 03 añade I/O seguro de archivos de texto con modos, encoding explícito, lectura, escritura, append, excepciones de archivo específicas y `with`. El próximo capítulo planificado es **TXT, CSV y JSON**. ## Fase 8: Biblioteca estándar diff --git a/docs/roadmap.pt-BR.md b/docs/roadmap.pt-BR.md index af4b5be..4827989 100644 --- a/docs/roadmap.pt-BR.md +++ b/docs/roadmap.pt-BR.md @@ -21,7 +21,7 @@ Este roadmap acompanha tanto a trilha educacional quanto a fundação do reposit | 4. Fluxo do programa | Concluída | Oito capítulos revisados cobrem condições, ramificações, correspondência de padrões estruturais, `for`, auxiliares de iteração, `while`, controle de loops e escolha e combinação das ferramentas de fluxo pela intenção | | 5. Funções | Concluída | Nove capítulos revisados cobrem `def`, chamadas, entradas obrigatórias, valores retornados, escopo, type hints, valores padrão seguros, argumentos flexíveis, composição de funções e fluxo explícito de dados | | 6. Comentários, documentação e código limpo | Concluída | Seis capítulos revisados estão disponíveis e a seção educacional-piloto está oficialmente concluída | -| 7. Erros, arquivos e módulos | Em andamento | Os Capítulos 01–02 cobrem tratamento de exceções de runtime e criação, relançamento, encadeamento e definição deliberada de exceções personalizadas | +| 7. Erros, arquivos e módulos | Em andamento | Os Capítulos 01–03 cobrem tratamento de exceções, sinalização deliberada e I/O seguro de arquivos de texto com `open()` e `with` | | 8. Biblioteca padrão | Planejada | Conteúdo ainda não iniciado | | 9. Bibliotecas externas | Planejada | Conteúdo ainda não iniciado | | 10. Projetos práticos | Planejada | Conteúdo ainda não iniciado | @@ -130,11 +130,11 @@ Consulte a [trilha de aprendizagem da seção](../errors-files-and-modules/READM - [x] [`try`, `except`, `else` e `finally`](../errors-files-and-modules/01-try-except-else-finally/README.pt-BR.md) - [x] [`raise` e exceções personalizadas](../errors-files-and-modules/02-raise-and-custom-exceptions/README.pt-BR.md) -- [ ] `open()` e `with` +- [x] [`open()` e `with`](../errors-files-and-modules/03-open-and-with/README.pt-BR.md) - [ ] TXT, CSV e JSON - [ ] Imports, módulos e pacotes -A Fase 7 está em andamento. O Capítulo 01 estabelece tratamento de exceções de runtime, handlers específicos, `else`, `finally`, propagação e fronteiras de falha estreitas. O Capítulo 02 acrescenta `raise` deliberado, escolha entre exceções built-in e personalizadas, relançamento com `raise` sem expressão, encadeamento explícito e `raise` versus `assert`. O próximo capítulo planejado é **`open()` e `with`**. +A Fase 7 está em andamento. Os Capítulos 01–02 estabelecem tratamento e sinalização deliberada de exceções. O Capítulo 03 acrescenta I/O seguro de arquivos de texto com modos, encoding explícito, leitura, escrita, append, exceções de arquivo específicas e `with`. O próximo capítulo planejado é **TXT, CSV e JSON**. ## Fase 8: Biblioteca padrão diff --git a/errors-files-and-modules/03-open-and-with/README.es.md b/errors-files-and-modules/03-open-and-with/README.es.md new file mode 100644 index 0000000..8db9911 --- /dev/null +++ b/errors-files-and-modules/03-open-and-with/README.es.md @@ -0,0 +1,847 @@ +
+ +# Abrir Archivos de Forma Segura con `open()` y `with` + +[🇺🇸 English](README.md) · [🇧🇷 Português](README.pt-BR.md) · [🇪🇸 Español](README.es.md) + +
+ +[← Volver a Errores, Archivos y Módulos](../README.es.md) · [← Anterior: Lanzar Excepciones y Crear Excepciones Personalizadas](../02-raise-and-custom-exceptions/README.es.md) + +Los programas suelen necesitar que los datos sigan existiendo después de que el proceso termina. Un archivo de texto puede almacenar notas, configuración, exportaciones, logs o resultados intermedios que una ejecución posterior podrá leer de nuevo. + +La función incorporada `open()` de Python crea un **objeto archivo** conectado a un archivo o a otro recurso similar a un archivo. La instrucción `with` da a ese recurso un tiempo de vida claro, de modo que se cierre incluso cuando el bloque termina debido a una excepción. + +Este capítulo se centra en **archivos de texto simples y gestión segura de recursos**. El Capítulo 04 utilizará esta base para trabajar con TXT, CSV y JSON como formatos de datos. + +**Tiempo estimado de estudio:** 100–130 minutos. + +**Requisito de Python:** Python 3.10 o posterior. El comportamiento de archivos enseñado aquí se verificó con la documentación oficial de Python 3.14. + +## Objetivos de aprendizaje + +Al final de este capítulo, deberías poder: + +- explicar qué devuelve `open()` y por qué un objeto archivo es un recurso que debe cerrarse; +- abrir archivos de texto con modos explícitos y una codificación explícita; +- explicar las diferencias prácticas entre `r`, `w`, `a` y `x`; +- leer un archivo pequeño completo, una línea o líneas de forma incremental; +- escribir y añadir texto controlando deliberadamente los caracteres de nueva línea; +- usar `with` para que un archivo se cierre tanto en salidas normales como excepcionales; +- conectar `with` con el papel de limpieza visto anteriormente con `finally`; +- manejar excepciones comunes de archivos en el límite apropiado; +- explicar por qué las rutas relativas dependen del directorio de trabajo actual; +- evitar truncados accidentales, sorpresas de codificación y lecturas completas innecesarias; +- distinguir modo texto de modo binario a nivel introductorio; +- elegir un patrón básico seguro para tareas comunes con archivos. + +## 1. Los archivos introducen persistencia + +Las variables viven en memoria mientras un proceso de Python está en ejecución. Cuando el proceso termina, las variables locales normales desaparecen. + +Un archivo da al programa un lugar donde almacenar datos fuera de ese proceso: + +```text +memoria del programa + ↓ escritura +archivo de texto en almacenamiento + ↓ lectura posterior +otra ejecución del programa +``` + +Esa persistencia es útil, pero también introduce nuevas posibilidades de fallo: una ruta puede no existir, el permiso puede ser denegado, el texto puede usar una codificación inesperada o el programa puede abrir un archivo existente en un modo destructivo. + +## 2. `open()` devuelve un objeto archivo + +Una llamada común en modo texto se parece a esta: + +```python +file = open("notes.txt", "r", encoding="utf-8") +``` + +`open()` no devuelve directamente el texto del archivo. Devuelve un **objeto archivo** que ofrece operaciones como `read()`, iteración, `write()` y `close()`. + +El objeto también mantiene estado, como si está abierto y cuál es la posición actual de lectura o escritura. + +## 3. El modelo simplificado de `open()` + +La función incorporada completa tiene más parámetros, pero un buen modelo para principiantes es: + +```python +open(file, mode="r", encoding=None) +``` + +Para archivos de texto, piensa en tres preguntas antes de abrir nada: + +1. **¿Qué ruta?** +2. **¿Qué operación se pretende: leer, reemplazar, añadir o crear solo si no existe?** +3. **¿Qué codificación de texto utiliza el archivo?** + +Hacer explícitas esas decisiones es más seguro que tratar `open()` como una operación mágica para "obtener el contenido del archivo". + +## 4. Modo `r`: leer un archivo existente + +`"r"` significa lectura de texto. También es el modo predeterminado cuando se omite el argumento de modo. + +```python +file = open("notes.txt", "r", encoding="utf-8") +``` + +El destino debe existir. Si no existe, `open()` lanza `FileNotFoundError`. + +Ser explícito con `"r"` suele ser útil en código educativo y de aplicación porque la operación pretendida queda visible de inmediato. + +## 5. Modo `w`: escribir y reemplazar + +`"w"` abre un archivo de texto para escritura. + +```python +file = open("notes.txt", "w", encoding="utf-8") +``` + +Si el archivo no existe, se crea. Si ya existe, su contenido anterior se **trunca** antes de escribir los nuevos datos. + +Ese comportamiento destructivo hace que la elección del modo sea una decisión de corrección, no un detalle cosmético. + +```text +archivo existente + "w" + ↓ +contenido anterior eliminado + ↓ +las nuevas escrituras son el contenido +``` + +## 6. Modo `a`: añadir al final + +`"a"` abre para añadir. Las nuevas escrituras se colocan al final en lugar de reemplazar el contenido existente. + +```python +with open("notes.txt", "a", encoding="utf-8") as file: + file.write("Files\n") +``` + +Si el archivo no existe, el modo de adición lo crea. + +El modo append es útil cuando el contenido anterior debe mantenerse intacto y cada nueva escritura pertenece al final. + +## 7. Modo `x`: crear solo si el archivo es nuevo + +`"x"` solicita creación exclusiva. + +```python +with open("notes.txt", "x", encoding="utf-8") as file: + file.write("First version\n") +``` + +Si la ruta ya existe, Python lanza `FileExistsError` en lugar de reemplazarla. + +Usa este modo cuando sobrescribir accidentalmente un archivo existente sería un error. + +## 8. Elige el modo según la intención + +Una tabla compacta de decisión: + +| Intención | Modo típico | Archivo existente | +|---|---|---| +| Leer | `r` | se conserva | +| Reemplazar contenido | `w` | se trunca | +| Añadir al final | `a` | se conserva | +| Crear solo si no existe | `x` | lanza `FileExistsError` | + +Existen combinaciones como `r+`, `w+` y `a+` para leer y escribir con el mismo objeto archivo. Son válidas, pero también combinan reglas de posición y de modo que los principiantes rara vez necesitan. + +Prefiere el modo más simple que corresponda al trabajo real. + +## 9. El modo texto requiere una decisión de codificación + +Los archivos de texto almacenan bytes, mientras que las strings de Python contienen texto Unicode. Una **codificación** define cómo se relacionan esas dos representaciones. + +```text +str en Python + ↓ codificar +bytes en el archivo + ↓ decodificar +str en Python +``` + +Si se omite `encoding`, `open()` usa un valor predeterminado que depende del entorno de ejecución. Eso puede hacer que el mismo código fuente se comporte de forma diferente en distintos sistemas. + +Cuando se sabe que el formato es UTF-8, indícalo explícitamente: + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + content = file.read() +``` + +## 10. Por qué `with` es el patrón normal para archivos + +Un objeto archivo utiliza un recurso del sistema operativo. Debe cerrarse cuando el programa termina de usarlo. + +El patrón manual funciona: + +```python +file = open("notes.txt", "r", encoding="utf-8") +content = file.read() +file.close() +``` + +Pero hay un problema: si ocurre una excepción entre `open()` y `close()`, la llamada final puede no ejecutarse. + +La solución habitual es `with`: + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + content = file.read() +``` + +Cuando la ejecución sale del bloque `with`, el protocolo de gestor de contexto del archivo realiza el trabajo de salida necesario y cierra el archivo. + +## 11. `with` se conecta directamente con `finally` + +El Capítulo 01 introdujo `finally` para la limpieza. Un gestor de contexto empaqueta ese patrón de limpieza detrás de un protocolo reutilizable. + +Conceptualmente: + +```text +adquirir recurso + ↓ +ejecutar bloque + ↓ +liberar recurso +``` + +Incluso si el bloque lanza una excepción, el gestor de contexto tiene la oportunidad de realizar su trabajo de salida antes de que la excepción continúe hacia afuera. + +Para objetos archivo normales, eso significa cerrar el archivo. `with` **no** significa "ignorar errores de archivo"; significa "gestionar de forma confiable el tiempo de vida del recurso". + +## 12. El archivo queda cerrado después del bloque + +El nombre asignado por `as file` sigue existiendo después del bloque, pero el objeto archivo subyacente está cerrado: + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + content = file.read() + +print(file.closed) +``` + +Salida: + +```text +True +``` + +Intentar realizar I/O normal sobre ese objeto archivo cerrado lanza `ValueError`. + +No diseñes código esperando seguir usando el archivo fuera de su bloque `with`. Pasa los datos que necesitas a objetos normales de Python. + +## 13. Lee un archivo pequeño con `read()` + +`read()` sin un argumento de tamaño lee desde la posición actual hasta el final del archivo. + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + content = file.read() + +print(content) +``` + +Esto es simple y apropiado para un archivo que se sabe que es pequeño. + +Para un archivo muy grande o de tamaño desconocido, leerlo todo de una vez puede usar memoria innecesaria. En ese caso, procesa el archivo de forma incremental. + +## 14. `read(size)` avanza la posición actual + +Un tamaño positivo solicita como máximo esa cantidad de caracteres en modo texto: + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + first = file.read(5) + second = file.read(5) +``` + +La segunda llamada continúa donde terminó la primera. Las lecturas de archivo mantienen estado. + +Al final del archivo, otro `read()` en modo texto devuelve una string vacía. + +Este modelo de posición se vuelve importante siempre que se realizan varias lecturas mediante el mismo objeto archivo. + +## 15. Lee una línea con `readline()` + +`readline()` lee una línea cada vez: + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + first_line = file.readline() + second_line = file.readline() +``` + +Cuando una línea termina con una nueva línea en el archivo, ese `\n` normalmente forma parte de la string devuelta. + +Al final del archivo, `readline()` devuelve `""`. + +Una línea en blanco que contiene solo el salto de línea es `"\n"`, lo que es diferente del final del archivo. + +## 16. Itera sobre el archivo para trabajar por líneas + +Para el procesamiento habitual línea por línea, itera sobre el objeto archivo: + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + for line in file: + print(line, end="") +``` + +Esto evita crear primero una lista con todas las líneas y es el patrón simple preferido para el procesamiento incremental por líneas. + +El objeto archivo es un iterable. El bucle consume líneas desde su posición actual. + +## 17. Sé deliberado al quitar saltos de línea + +Un patrón tentador es: + +```python +clean = line.strip() +``` + +Pero `strip()` elimina espacios en blanco al principio y al final, no solo el salto de línea. Eso puede cambiar datos significativos. + +Si el único cambio pretendido es eliminar un carácter de nueva línea final, sé más específico: + +```python +clean = line.rstrip("\n") +``` + +Eliminar o no otros espacios en blanco es una decisión del formato de datos, no una regla universal de archivos. + +## 18. `readlines()` crea una lista + +`readlines()` devuelve las líneas restantes como una lista: + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + lines = file.readlines() +``` + +Puede ser conveniente cuando el conjunto completo de líneas es pequeño y realmente necesitas operaciones de lista después. + +No lo uses automáticamente. Si cada línea puede procesarse de forma independiente, iterar sobre el archivo mantiene el uso de memoria más simple y escalable. + +## 19. Escribe texto con `write()` + +En modo texto, `write()` espera una string: + +```python +with open("notes.txt", "w", encoding="utf-8") as file: + file.write("Functions\n") + file.write("Exceptions\n") +``` + +`write()` **no** añade un salto de línea automáticamente. Si el archivo debe contener saltos de línea, inclúyelos de forma explícita. + +El método devuelve la cantidad de caracteres escritos en modo texto: + +```python +with open("notes.txt", "w", encoding="utf-8") as file: + count = file.write("Python\n") + +print(count) +``` + +## 20. Convierte valores no string antes de escribir texto + +`write()` en modo texto no formatea objetos arbitrarios de Python por ti: + +```python +score = 92 + +with open("score.txt", "w", encoding="utf-8") as file: + file.write(str(score)) +``` + +Una f-string suele ser más clara cuando se necesitan etiquetas o formato: + +```python +with open("score.txt", "w", encoding="utf-8") as file: + file.write(f"score={score}\n") +``` + +El Capítulo 04 introducirá formatos estructurados que ofrecen mejores convenciones para almacenar datos más complejos. + +## 21. `writelines()` no inventa separadores + +`writelines()` escribe strings de un iterable, pero no añade caracteres de nueva línea entre ellas: + +```python +lines = ["Functions\n", "Exceptions\n", "Files\n"] + +with open("notes.txt", "w", encoding="utf-8") as file: + file.writelines(lines) +``` + +Si las strings no contienen ya separadores, el resultado quedará unido. + +Para principiantes, llamadas repetidas a `write()` suelen ser más fáciles de inspeccionar hasta que la forma exacta de los datos esté clara. + +## 22. Las rutas relativas dependen del directorio de trabajo actual + +Una ruta como: + +```python +open("data/notes.txt", "r", encoding="utf-8") +``` + +es **relativa**. Python la resuelve desde el directorio de trabajo actual del proceso, que no tiene por qué ser el mismo directorio que contiene el archivo `.py`. + +Eso explica una sorpresa común para principiantes: + +```text +mismo código fuente ++ directorio de trabajo diferente += ruta resuelta diferente +``` + +Capítulos posteriores introducirán `pathlib`, que ofrece una API de rutas más rica. Por ahora, conoce siempre desde qué directorio se ejecuta tu proceso al usar rutas relativas. + +## 23. Las rutas absolutas identifican una ubicación desde una raíz del sistema de archivos + +Una ruta absoluta no depende del directorio de trabajo actual de la misma forma. Su sintaxis exacta es específica de la plataforma. + +Codificar de forma fija una ruta absoluta de un solo equipo dentro de código reutilizable suele ser un problema de portabilidad. + +Prefiere recibir rutas mediante configuración, argumentos o una estrategia de construcción de rutas apropiada para el programa en lugar de incrustar en el código la estructura de la máquina de un desarrollador. + +## 24. Excepciones comunes de archivos + +Las operaciones de archivo pueden lanzar varios tipos útiles de excepción: + +| Excepción | Significado típico | +|---|---| +| `FileNotFoundError` | una ruta necesaria no existe | +| `FileExistsError` | la creación exclusiva apuntó a una ruta existente | +| `PermissionError` | la operación no está permitida | +| `IsADirectoryError` | una operación de archivo apuntó a un directorio | +| `UnicodeDecodeError` | los bytes no pudieron decodificarse con la codificación de texto elegida | +| `OSError` | fallos más amplios de I/O del sistema operativo | + +Estos tipos son señales, no instrucciones para capturarlo todo. Maneja una excepción solo donde el programa tenga una respuesta significativa. + +## 25. Coloca `try` alrededor del límite que puedes manejar + +Si un archivo opcional ausente tiene un fallback claro, captura ese fallo específico: + +```python +try: + with open("preferences.txt", "r", encoding="utf-8") as file: + preferences = file.read() +except FileNotFoundError: + preferences = "" +``` + +El `with` sigue encargándose del cierre siempre que la apertura tenga éxito. + +Un `except OSError:` amplio puede ser apropiado cuando varios fallos del sistema operativo realmente comparten la misma política, pero no debe usarse solo para hacer desaparecer todos los problemas de archivo. + +## 26. Si el cuerpo falla, la limpieza ocurre antes de la propagación + +Considera: + +```python +with open("scores.txt", "r", encoding="utf-8") as file: + score = int(file.readline()) +``` + +Si la línea contiene texto inválido para un entero, `int()` lanza `ValueError`. + +El gestor de contexto del archivo realiza su trabajo de salida mientras se abandona el bloque, y la excepción continúa hacia afuera salvo que algún código circundante la maneje. + +Esa es la composición clave: + +```text +apertura correcta + ↓ +el cuerpo lanza una excepción + ↓ +el archivo se cierra + ↓ +la excepción se propaga +``` + +## 27. Separa el acceso al archivo de la interpretación de datos cuando sea útil + +Un diseño útil consiste en dejar que una función lea el texto y otra lo interprete: + +```python +def read_text(path: str) -> str: + with open(path, "r", encoding="utf-8") as file: + return file.read() + + +def parse_score(text: str) -> int: + score = int(text) + if not 0 <= score <= 100: + raise ValueError("score must be between 0 and 100") + return score +``` + +Ahora los fallos de archivo y los fallos de validación del contenido son conceptualmente distintos. + +Esa separación se vuelve especialmente útil en el Capítulo 04 al interpretar datos estructurados. + +## 28. Valida antes de escrituras destructivas cuando sea práctico + +Como `"w"` trunca un archivo existente cuando se abre, valida los datos que puedan validarse **antes** de abrir el destino en modo escritura. + +Prefiere este orden: + +```text +construir o validar datos de salida + ↓ +abrir destino con "w" + ↓ +escribir texto validado +``` + +en lugar de abrir primero el destino y descubrir después que los datos son inválidos. + +Esto no hace que la escritura sea atómica ni protege contra todos los fallos posibles, pero reduce una clase evitable de pérdida accidental de datos. + +## 29. El modo texto y el modo binario son interfaces diferentes + +El modo texto es el predeterminado y trabaja con `str`. + +El modo binario añade `"b"` al modo y trabaja con `bytes`: + +```python +with open("image.bin", "rb") as file: + data = file.read() +``` + +En modo binario no se usa codificación de texto porque Python no está convirtiendo entre `str` y bytes del archivo. + +Este capítulo se concentra en el modo texto. Usa modo binario cuando el formato de datos es fundamentalmente bytes, como muchas imágenes, archivos comprimidos o cargas útiles de protocolos. + +## 30. No pases `encoding` en modo binario + +Esta combinación es conceptualmente incorrecta: + +```python +open("data.bin", "rb", encoding="utf-8") +``` + +El modo binario expone bytes directamente, por lo que un parámetro de codificación no forma parte de esa interfaz. + +Elige un modelo: + +```text +modo texto → str + encoding +modo binario → bytes +``` + +## 31. Varios gestores de contexto pueden compartir un `with` + +Python puede gestionar más de un contexto en una sola instrucción: + +```python +with ( + open("input.txt", "r", encoding="utf-8") as source, + open("output.txt", "w", encoding="utf-8") as destination, +): + destination.write(source.read()) +``` + +Ambos recursos reciben su tratamiento de salida correspondiente. + +Para principiantes, las instrucciones `with` anidadas o con varios elementos son más útiles cuando la operación realmente necesita ambos recursos al mismo tiempo. No abras archivos antes de tiempo ni los mantengas abiertos más de lo necesario. + +## 32. Ejemplo práctico: escribir y luego leer + +El primer ejemplo ejecutable crea un directorio temporal solo para que la prueba del repositorio ejercite I/O real de archivos sin dejar archivos generados. + +```python +import os +import tempfile + + +with tempfile.TemporaryDirectory() as directory: + path = os.path.join(directory, "topics.txt") + + with open(path, "w", encoding="utf-8") as file: + file.write("Functions\n") + file.write("Exceptions\n") + file.write("Files\n") + + with open(path, "r", encoding="utf-8") as file: + for line in file: + print(line.rstrip("\n")) +``` + +Salida: + +```text +Functions +Exceptions +Files +``` + +Los auxiliares `tempfile` y `os.path` sirven solo para mantener limpio el ejemplo ejecutable. El objetivo de aprendizaje del capítulo son los dos bloques `with open(...)`. + +Versión ejecutable: [`examples/write_and_read_text.py`](examples/write_and_read_text.py). + +## 33. Ejemplo práctico: añadir sin reemplazar + +El segundo ejemplo hace visible la diferencia entre `"w"` y `"a"`: + +```python +import os +import tempfile + + +with tempfile.TemporaryDirectory() as directory: + path = os.path.join(directory, "history.txt") + + with open(path, "w", encoding="utf-8") as file: + file.write("Chapter 01\n") + + with open(path, "a", encoding="utf-8") as file: + file.write("Chapter 02\n") + file.write("Chapter 03\n") + + with open(path, "r", encoding="utf-8") as file: + print(file.read(), end="") +``` + +Salida: + +```text +Chapter 01 +Chapter 02 +Chapter 03 +``` + +Versión ejecutable: [`examples/append_text.py`](examples/append_text.py). + +## 34. Ejemplo práctico: manejar un archivo opcional ausente + +El tercer ejemplo conecta el acceso a archivos con el modelo de excepciones de los Capítulos 01 y 02: + +```python +import os +import tempfile + + +with tempfile.TemporaryDirectory() as directory: + path = os.path.join(directory, "optional.txt") + + try: + with open(path, "r", encoding="utf-8") as file: + content = file.read() + except FileNotFoundError: + content = "default settings" + + print(content) +``` + +Salida: + +```text +default settings +``` + +El fallback es significativo porque este archivo es explícitamente opcional. Un archivo obligatorio normalmente necesitaría una política diferente. + +Versión ejecutable: [`examples/handle_missing_file.py`](examples/handle_missing_file.py). + +## 35. Error común: abrir con `w` cuando querías `a` + +Esto reemplaza el contenido anterior: + +```python +with open("history.txt", "w", encoding="utf-8") as file: + file.write("new entry\n") +``` + +Si la intención era conservar el historial anterior y añadir una entrada, usa `"a"`. + +Antes de cada `open()` capaz de escribir, pregúntate si el contenido existente debe reemplazarse, conservarse o protegerse contra sobrescritura. + +## 36. Error común: olvidar la codificación + +Esto depende de la codificación de texto predeterminada del entorno: + +```python +with open("notes.txt", "r") as file: + content = file.read() +``` + +Si el formato del archivo está definido como UTF-8, indícalo: + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + content = file.read() +``` + +La codificación explícita hace visible la intención y evita una fuente importante de sorpresas entre plataformas. + +## 37. Error común: cierre manual con una brecha para excepciones + +Esto tiene una brecha de limpieza: + +```python +file = open("scores.txt", "r", encoding="utf-8") +score = int(file.readline()) +file.close() +``` + +Si `int()` lanza una excepción, `close()` se omite. + +Prefiere: + +```python +with open("scores.txt", "r", encoding="utf-8") as file: + score = int(file.readline()) +``` + +Ahora la limpieza del recurso está ligada al tiempo de vida del bloque. + +## 38. Error común: tratar todos los problemas de archivo como si fueran iguales + +Evita agrupar fallos no relacionados sin motivo: + +```python +try: + with open("settings.txt", "r", encoding="utf-8") as file: + settings = file.read() +except Exception: + settings = "" +``` + +Esto puede ocultar errores de programación y fallos inesperados. + +Elige una excepción específica cuando la política de recuperación sea específica. Si varias subclases de `OSError` realmente comparten la misma política, documenta esa decisión más amplia. + +## 39. Error común: usar `read()` automáticamente para todo archivo + +Leer el archivo completo es conveniente, no universalmente óptimo. + +Si la tarea es "procesar cada línea de forma independiente", esto suele ser mejor: + +```python +with open("events.txt", "r", encoding="utf-8") as file: + for line in file: + process(line) +``` + +que cargar primero todas las líneas en una string enorme. + +Elige la estrategia de lectura a partir del tamaño y del modelo de procesamiento de los datos. + +## 40. Las rutas provenientes de usuarios son un límite de entrada + +Si un programa acepta una ruta de un usuario, una solicitud de API, un archivo de configuración o un argumento de línea de comandos, esa ruta es una entrada. + +Una operación con capacidad de escritura puede modificar o crear datos en la ubicación resuelta. + +Las aplicaciones con requisitos de seguridad o protección de datos deben validar o limitar las ubicaciones permitidas según su propia política. La política exacta depende del programa y queda fuera de este capítulo introductorio. + +La lección general es simple: **una ruta no es metadato inofensivo cuando el programa va a leer o escribir en ella.** + +## 41. Cuándo no usar archivos de texto sin estructura como todo el modelo de datos + +El texto simple es excelente para contenido simple, pero inventar manualmente separadores y reglas de parsing se vuelve frágil a medida que los datos ganan estructura. + +Por ejemplo: + +```text +name|score|date|notes +``` + +plantea preguntas sobre escape de `|`, campos ausentes, tipos y saltos de línea incrustados. + +El Capítulo 04 introduce TXT, CSV y JSON para que la elección del formato corresponda a la forma de los datos en lugar de forzar cada problema a un parsing de texto improvisado. + +## 42. Ejercicio + +Crea un pequeño programa llamado `study_notes.py` con estos requisitos: + +1. Empieza con tres nombres de temas en una lista. +2. Abre `study_notes.txt` con `"w"` y `encoding="utf-8"`. +3. Escribe un tema por línea. +4. Vuelve a abrir el archivo con `"a"` y añade un tema más. +5. Vuelve a abrirlo con `"r"` e itera sobre las líneas. +6. Muestra cada tema sin una línea en blanco adicional. +7. Usa `with` para cada operación de archivo. +8. Explica en un comentario por qué `"w"` es apropiado en la primera apertura y `"a"` en la segunda. + +Preguntas extra: + +- ¿Qué ocurriría si el primer modo fuera `"x"` y el archivo ya existiera? +- ¿Qué excepción esperarías al intentar leer un archivo ausente? +- ¿Por qué `read()` podría ser una mala elección si el archivo pudiera contener millones de líneas? + +## 43. Lista de revisión + +Antes de continuar, comprueba que puedes responder sin adivinar: + +- ¿Qué devuelve `open()`? +- ¿Por qué `with open(...)` es más seguro que un par manual `open()` / `close()`? +- ¿Qué hace `"w"` con un archivo existente? +- ¿En qué se diferencia `"a"`? +- ¿Cuándo `"x"` lanza `FileExistsError`? +- ¿Por qué UTF-8 suele escribirse explícitamente como `encoding="utf-8"`? +- ¿Qué devuelve `read()` al final del archivo en modo texto? +- ¿Por qué iterar sobre un archivo puede ser preferible a `readlines()`? +- ¿`write()` añade `\n` automáticamente? +- ¿Qué ocurre con el archivo cuando una excepción sale del cuerpo de `with`? +- ¿Desde qué directorio se resuelve una ruta relativa? +- ¿Cuál es la diferencia básica entre modo texto y modo binario? + +## 44. Referencia rápida + +| Necesidad | Patrón | +|---|---| +| Leer texto UTF-8 | `with open(path, "r", encoding="utf-8") as file:` | +| Reemplazar texto UTF-8 | `with open(path, "w", encoding="utf-8") as file:` | +| Añadir texto UTF-8 | `with open(path, "a", encoding="utf-8") as file:` | +| Crear solo si no existe | `with open(path, "x", encoding="utf-8") as file:` | +| Leer todo el texto restante | `file.read()` | +| Leer una línea | `file.readline()` | +| Procesar líneas incrementalmente | `for line in file:` | +| Escribir texto | `file.write(text)` | +| Quitar solo `\n` final | `line.rstrip("\n")` | +| Ruta necesaria ausente | `FileNotFoundError` | +| Ruta existente con `x` | `FileExistsError` | +| Categoría general de I/O del SO | `OSError` | +| Lectura binaria | `with open(path, "rb") as file:` | + +Patrón inicial recomendado: + +```python +with open(path, "r", encoding="utf-8") as file: + content = file.read() +``` + +Elige el modo según la intención, especifica una codificación de texto conocida, mantén corto el tiempo de vida del archivo y captura solo fallos para los que el código circundante tenga una política real. + +## Qué sigue + +El Capítulo 03 establece acceso seguro a archivos de texto y tiempo de vida de recursos. El siguiente capítulo, **TXT, CSV y JSON**, se centrará en cómo se representan los datos dentro de los archivos y qué parser o escritor debe ser responsable de cada límite de formato. + +```text +excepciones + ↓ +lanzamiento deliberado + ↓ +tiempo de vida seguro con open() + with + ↓ +formatos TXT / CSV / JSON + ↓ +módulos y paquetes +``` + +## Referencias oficiales + +- Documentación de Python 3.14 para `open()` incorporado: +- Tutorial de Python 3.14, Reading and Writing Files: +- Referencia del lenguaje Python 3.14, instrucción `with`: +- Documentación `io` de Python 3.14, Text Encoding: diff --git a/errors-files-and-modules/03-open-and-with/README.md b/errors-files-and-modules/03-open-and-with/README.md new file mode 100644 index 0000000..d7406c5 --- /dev/null +++ b/errors-files-and-modules/03-open-and-with/README.md @@ -0,0 +1,847 @@ +
+ +# Opening Files Safely with `open()` and `with` + +[🇺🇸 English](README.md) · [🇧🇷 Português](README.pt-BR.md) · [🇪🇸 Español](README.es.md) + +
+ +[← Back to Errors, Files, and Modules](../README.md) · [← Previous: Raising and Custom Exceptions](../02-raise-and-custom-exceptions/README.md) + +Programs often need data to survive after the process ends. A text file can store notes, configuration, exports, logs, or intermediate results that a later execution can read again. + +Python's built-in `open()` function creates a **file object** connected to a file or another file-like resource. The `with` statement gives that resource a clear lifetime so it is closed even when the block exits because of an exception. + +This chapter focuses on **plain text files and safe resource management**. Chapter 04 will build on this foundation with TXT, CSV, and JSON as data formats. + +**Estimated study time:** 100–130 minutes. + +**Python requirement:** Python 3.10 or newer. The file-handling behavior taught here was verified against the official Python 3.14 documentation. + +## Learning goals + +By the end of this chapter, you should be able to: + +- explain what `open()` returns and why a file object is a resource that should be closed; +- open text files with explicit modes and an explicit encoding; +- explain the practical differences among `r`, `w`, `a`, and `x`; +- read a complete small file, one line, or lines incrementally; +- write and append text while controlling newline characters deliberately; +- use `with` so a file is closed on normal and exceptional exit paths; +- connect `with` to the cleanup role previously seen with `finally`; +- handle common file exceptions at an appropriate boundary; +- explain why relative paths depend on the current working directory; +- avoid accidental truncation, encoding surprises, and unnecessary whole-file reads; +- distinguish text mode from binary mode at a beginner-friendly level; +- choose a safe basic pattern for common file tasks. + +## 1. Files introduce persistence + +Variables live in memory while a Python process is running. When the process ends, ordinary local variables disappear. + +A file gives a program a place to store data outside that process: + +```text +program memory + ↓ write +text file on storage + ↓ read later +another program execution +``` + +That persistence is useful, but it also introduces new failure possibilities: a path may not exist, permission may be denied, text may use an unexpected encoding, or a program may open an existing file in a destructive mode. + +## 2. `open()` returns a file object + +A common text-mode call looks like this: + +```python +file = open("notes.txt", "r", encoding="utf-8") +``` + +`open()` does not return the file's text directly. It returns a **file object** that provides operations such as `read()`, iteration, `write()`, and `close()`. + +The object also tracks state such as whether it is open and where the current read or write position is. + +## 3. The simplified `open()` model + +The complete built-in function has more parameters, but a strong beginner model is: + +```python +open(file, mode="r", encoding=None) +``` + +For text files, think about three questions before opening anything: + +1. **Which path?** +2. **What operation is intended: read, replace, append, or create-only?** +3. **Which text encoding does the file use?** + +Making those choices explicit is safer than treating `open()` as a magical "get file contents" operation. + +## 4. Mode `r`: read an existing file + +`"r"` means read text. It is also the default mode when the mode argument is omitted. + +```python +file = open("notes.txt", "r", encoding="utf-8") +``` + +The target must exist. If it does not, `open()` raises `FileNotFoundError`. + +Being explicit with `"r"` is often useful in educational and application code because the intended operation is immediately visible. + +## 5. Mode `w`: write and replace + +`"w"` opens a text file for writing. + +```python +file = open("notes.txt", "w", encoding="utf-8") +``` + +If the file does not exist, it is created. If it already exists, its previous contents are **truncated** before new data is written. + +That destructive behavior makes mode selection a correctness decision, not a cosmetic detail. + +```text +existing file + "w" + ↓ +old contents removed + ↓ +new writes become the contents +``` + +## 6. Mode `a`: append to the end + +`"a"` opens for appending. New writes are added at the end instead of replacing the existing contents. + +```python +with open("notes.txt", "a", encoding="utf-8") as file: + file.write("Files\n") +``` + +If the file does not exist, append mode creates it. + +Append is useful when the previous contents should remain intact and each new write belongs after them. + +## 7. Mode `x`: create only if the file is new + +`"x"` requests exclusive creation. + +```python +with open("notes.txt", "x", encoding="utf-8") as file: + file.write("First version\n") +``` + +If the path already exists, Python raises `FileExistsError` instead of replacing it. + +Use this when accidentally overwriting an existing file would be an error. + +## 8. Choose the mode by intent + +A compact decision table: + +| Intent | Typical mode | Existing file | +|---|---|---| +| Read | `r` | kept | +| Replace contents | `w` | truncated | +| Add at the end | `a` | kept | +| Create only when absent | `x` | raises `FileExistsError` | + +There are combinations such as `r+`, `w+`, and `a+` for reading and writing with the same file object. They are valid, but they also combine positioning and mode rules that beginners rarely need. + +Prefer the simplest mode that matches the actual job. + +## 9. Text mode needs an encoding decision + +Text files store bytes, while Python strings contain Unicode text. An **encoding** defines how those two representations map to each other. + +```text +str in Python + ↓ encode +bytes in file + ↓ decode +str in Python +``` + +If `encoding` is omitted, `open()` uses a default that depends on the runtime environment. That can make the same source code behave differently on different systems. + +When the format is known to be UTF-8, state it explicitly: + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + content = file.read() +``` + +## 10. Why `with` is the normal file pattern + +A file object uses an operating-system resource. It should be closed when the program finishes using it. + +The manual pattern works: + +```python +file = open("notes.txt", "r", encoding="utf-8") +content = file.read() +file.close() +``` + +But there is a problem: if an exception occurs between `open()` and `close()`, the final call may never execute. + +The usual solution is `with`: + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + content = file.read() +``` + +When execution leaves the `with` block, the file's context-manager protocol performs the required exit work and closes the file. + +## 11. `with` connects directly to `finally` + +Chapter 01 introduced `finally` for cleanup. A context manager packages that cleanup pattern behind a reusable protocol. + +Conceptually: + +```text +acquire resource + ↓ +run block + ↓ +release resource +``` + +Even if the block raises an exception, the context manager is given a chance to perform its exit work before the exception continues outward. + +For ordinary file objects, that means the file is closed. `with` does **not** mean "ignore file errors"; it means "manage the resource lifetime reliably. + +## 12. The file is closed after the block + +The name assigned by `as file` still exists after the block, but the underlying file object is closed: + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + content = file.read() + +print(file.closed) +``` + +Output: + +```text +True +``` + +Trying to perform normal I/O on that closed file object raises `ValueError`. + +Do not design code that expects to keep using the file outside its `with` block. Move the data you need into ordinary Python objects instead. + +## 13. Read a small file with `read()` + +`read()` without a size argument reads from the current position to the end of the file. + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + content = file.read() + +print(content) +``` + +This is simple and appropriate for a file that is known to be small. + +For a very large or unbounded file, reading everything at once can use unnecessary memory. In that case, process the file incrementally. + +## 14. `read(size)` advances the current position + +A positive size asks for at most that many characters in text mode: + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + first = file.read(5) + second = file.read(5) +``` + +The second call continues from where the first call stopped. File reads are stateful. + +At end-of-file, another text-mode `read()` returns an empty string. + +This position model becomes important whenever multiple reads are performed through the same file object. + +## 15. Read one line with `readline()` + +`readline()` reads one line at a time: + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + first_line = file.readline() + second_line = file.readline() +``` + +When a line ends with a newline in the file, that `\n` is normally part of the returned string. + +At end-of-file, `readline()` returns `""`. + +A blank line containing only a newline is `"\n"`, which is different from end-of-file. + +## 16. Iterate over the file for line-oriented work + +For ordinary line-by-line processing, iterate over the file object: + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + for line in file: + print(line, end="") +``` + +This avoids first building a list containing every line and is the preferred simple pattern for incremental line processing. + +The file object is an iterable. The loop consumes lines from its current position. + +## 17. Be deliberate when removing newline characters + +A tempting pattern is: + +```python +clean = line.strip() +``` + +But `strip()` removes leading and trailing whitespace, not only the newline. That may change meaningful data. + +If the only intended change is removing a trailing newline character, be more specific: + +```python +clean = line.rstrip("\n") +``` + +Whether other whitespace should be removed is a data-format decision, not a universal file rule. + +## 18. `readlines()` builds a list + +`readlines()` returns the remaining lines as a list: + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + lines = file.readlines() +``` + +This can be convenient when the complete set of lines is small and you truly need list operations afterward. + +Do not use it automatically. If each line can be processed independently, iterating over the file keeps the memory model simpler and more scalable. + +## 19. Write text with `write()` + +In text mode, `write()` expects a string: + +```python +with open("notes.txt", "w", encoding="utf-8") as file: + file.write("Functions\n") + file.write("Exceptions\n") +``` + +`write()` does **not** add a newline automatically. If the file should contain line breaks, include them explicitly. + +The method returns the number of characters written in text mode: + +```python +with open("notes.txt", "w", encoding="utf-8") as file: + count = file.write("Python\n") + +print(count) +``` + +## 20. Convert non-string values before text writes + +Text-mode `write()` does not format arbitrary Python objects for you: + +```python +score = 92 + +with open("score.txt", "w", encoding="utf-8") as file: + file.write(str(score)) +``` + +An f-string is often clearer when labels or formatting are needed: + +```python +with open("score.txt", "w", encoding="utf-8") as file: + file.write(f"score={score}\n") +``` + +Chapter 04 will introduce structured formats that provide better conventions for storing more complex data. + +## 21. `writelines()` does not invent separators + +`writelines()` writes strings from an iterable, but it does not add newline characters between them: + +```python +lines = ["Functions\n", "Exceptions\n", "Files\n"] + +with open("notes.txt", "w", encoding="utf-8") as file: + file.writelines(lines) +``` + +If the strings do not already contain separators, the result will run together. + +For beginners, repeated `write()` calls are often easier to inspect until the exact data shape is clear. + +## 22. Relative paths depend on the current working directory + +A path such as: + +```python +open("data/notes.txt", "r", encoding="utf-8") +``` + +is **relative**. Python resolves it from the process's current working directory, which is not guaranteed to be the same directory that contains the `.py` file. + +That explains a common beginner surprise: + +```text +same source code ++ different working directory += different resolved path +``` + +Later chapters will introduce `pathlib`, which provides a richer path API. For now, always know which directory your process is running from when using relative paths. + +## 23. Absolute paths identify a location from a filesystem root + +An absolute path does not depend on the current working directory in the same way. Its exact syntax is platform-specific. + +Hard-coding an absolute path from one computer into reusable source code is usually a portability problem. + +Prefer to receive paths through configuration, arguments, or a path-building strategy appropriate to the program rather than embedding one developer's machine layout in the code. + +## 24. Common file exceptions + +File operations can raise several useful exception types: + +| Exception | Typical meaning | +|---|---| +| `FileNotFoundError` | a required path does not exist | +| `FileExistsError` | exclusive creation targeted an existing path | +| `PermissionError` | the operation is not permitted | +| `IsADirectoryError` | a file operation targeted a directory | +| `UnicodeDecodeError` | bytes could not be decoded with the selected text encoding | +| `OSError` | broader operating-system I/O failures | + +These are signals, not instructions to catch everything. Handle an exception only where the program has a meaningful response. + +## 25. Place `try` around the boundary you can handle + +If a missing optional file has a clear fallback, catch that specific failure: + +```python +try: + with open("preferences.txt", "r", encoding="utf-8") as file: + preferences = file.read() +except FileNotFoundError: + preferences = "" +``` + +The `with` still handles closing whenever opening succeeds. + +A broad `except OSError:` may be appropriate when several operating-system failures truly have the same policy, but it should not be used merely to make all file problems disappear. + +## 26. If the body fails, cleanup happens before propagation + +Consider: + +```python +with open("scores.txt", "r", encoding="utf-8") as file: + score = int(file.readline()) +``` + +If the line contains invalid integer text, `int()` raises `ValueError`. + +The file context manager performs its exit work as the block is left, and the exception continues outward unless some surrounding code handles it. + +That is the key composition: + +```text +open succeeds + ↓ +body raises + ↓ +file is closed + ↓ +exception propagates +``` + +## 27. Separate file access from data interpretation when useful + +A useful design is to let one function read text and another interpret it: + +```python +def read_text(path: str) -> str: + with open(path, "r", encoding="utf-8") as file: + return file.read() + + +def parse_score(text: str) -> int: + score = int(text) + if not 0 <= score <= 100: + raise ValueError("score must be between 0 and 100") + return score +``` + +Now file failures and content-validation failures are conceptually distinct. + +That separation becomes especially useful in Chapter 04 when parsing structured data. + +## 28. Validate before destructive writes when practical + +Because `"w"` truncates an existing file when it is opened, validate data that can be validated **before** opening the destination in write mode. + +Prefer this order: + +```text +build or validate output data + ↓ +open destination with "w" + ↓ +write validated text +``` + +over opening the destination first and only then discovering that the data is invalid. + +This does not make writing atomic or protect against every possible failure, but it reduces one avoidable class of accidental data loss. + +## 29. Text mode and binary mode are different interfaces + +Text mode is the default and works with `str`. + +Binary mode adds `"b"` to the mode and works with `bytes`: + +```python +with open("image.bin", "rb") as file: + data = file.read() +``` + +In binary mode, text encoding is not used because Python is not converting between `str` and file bytes. + +This chapter concentrates on text mode. Use binary mode when the data format is fundamentally bytes, such as many images, archives, or protocol payloads. + +## 30. Do not pass `encoding` in binary mode + +This combination is conceptually wrong: + +```python +open("data.bin", "rb", encoding="utf-8") +``` + +Binary mode exposes bytes directly, so an encoding parameter is not part of that interface. + +Choose one model: + +```text +text mode → str + encoding +binary mode → bytes +``` + +## 31. Multiple context managers can share one `with` + +Python can manage more than one context in a single statement: + +```python +with ( + open("input.txt", "r", encoding="utf-8") as source, + open("output.txt", "w", encoding="utf-8") as destination, +): + destination.write(source.read()) +``` + +Both resources receive their corresponding exit handling. + +For a beginner, nested or multi-item `with` statements are most useful when the operation genuinely needs both resources at the same time. Do not open files earlier or keep them open longer than necessary. + +## 32. Practical example: write, then read + +The first runnable example creates a temporary directory only so the repository test can exercise real file I/O without leaving generated files behind. + +```python +import os +import tempfile + + +with tempfile.TemporaryDirectory() as directory: + path = os.path.join(directory, "topics.txt") + + with open(path, "w", encoding="utf-8") as file: + file.write("Functions\n") + file.write("Exceptions\n") + file.write("Files\n") + + with open(path, "r", encoding="utf-8") as file: + for line in file: + print(line.rstrip("\n")) +``` + +Output: + +```text +Functions +Exceptions +Files +``` + +The `tempfile` and `os.path` helpers are housekeeping for the executable example. The chapter's learning target is the two `with open(...)` blocks. + +Runnable version: [`examples/write_and_read_text.py`](examples/write_and_read_text.py). + +## 33. Practical example: append without replacing + +The second example makes the difference between `"w"` and `"a"` visible: + +```python +import os +import tempfile + + +with tempfile.TemporaryDirectory() as directory: + path = os.path.join(directory, "history.txt") + + with open(path, "w", encoding="utf-8") as file: + file.write("Chapter 01\n") + + with open(path, "a", encoding="utf-8") as file: + file.write("Chapter 02\n") + file.write("Chapter 03\n") + + with open(path, "r", encoding="utf-8") as file: + print(file.read(), end="") +``` + +Output: + +```text +Chapter 01 +Chapter 02 +Chapter 03 +``` + +Runnable version: [`examples/append_text.py`](examples/append_text.py). + +## 34. Practical example: handle a missing optional file + +The third example connects file access to the exception model from Chapters 01 and 02: + +```python +import os +import tempfile + + +with tempfile.TemporaryDirectory() as directory: + path = os.path.join(directory, "optional.txt") + + try: + with open(path, "r", encoding="utf-8") as file: + content = file.read() + except FileNotFoundError: + content = "default settings" + + print(content) +``` + +Output: + +```text +default settings +``` + +The fallback is meaningful because this file is explicitly optional. A required file would normally need a different policy. + +Runnable version: [`examples/handle_missing_file.py`](examples/handle_missing_file.py). + +## 35. Common mistake: opening with `w` when you meant `a` + +This replaces previous contents: + +```python +with open("history.txt", "w", encoding="utf-8") as file: + file.write("new entry\n") +``` + +If the intent was to preserve the old history and add one entry, use `"a"`. + +Before every write-capable `open()`, ask whether existing contents should be replaced, preserved, or protected from overwrite. + +## 36. Common mistake: forgetting the encoding + +This relies on the environment's default text encoding: + +```python +with open("notes.txt", "r") as file: + content = file.read() +``` + +If the file format is defined as UTF-8, say so: + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + content = file.read() +``` + +Explicit encoding makes intent visible and avoids a major source of cross-platform surprises. + +## 37. Common mistake: manual close with an exception gap + +This has a cleanup gap: + +```python +file = open("scores.txt", "r", encoding="utf-8") +score = int(file.readline()) +file.close() +``` + +If `int()` raises, `close()` is skipped. + +Prefer: + +```python +with open("scores.txt", "r", encoding="utf-8") as file: + score = int(file.readline()) +``` + +Now resource cleanup is tied to the block's lifetime. + +## 38. Common mistake: catching every file problem as if it were the same + +Avoid collapsing unrelated failures without a reason: + +```python +try: + with open("settings.txt", "r", encoding="utf-8") as file: + settings = file.read() +except Exception: + settings = "" +``` + +This can hide programming errors and unexpected failures. + +Choose a specific exception when the recovery policy is specific. If several `OSError` subclasses genuinely have the same policy, document that broader decision. + +## 39. Common mistake: using `read()` automatically for every file + +Whole-file reading is convenient, not universally optimal. + +If the task is "process each line independently", this is often better: + +```python +with open("events.txt", "r", encoding="utf-8") as file: + for line in file: + process(line) +``` + +than first loading all lines into one giant string. + +Choose the reading strategy from the size and processing model of the data. + +## 40. Paths from users are an input boundary + +If a program accepts a path from a user, API request, configuration file, or command-line argument, that path is input. + +A write-capable operation can modify or create data at the resolved location. + +Applications with security or data-protection requirements should validate or constrain allowed locations according to their own policy. The exact policy depends on the program and is beyond this beginner chapter. + +The general lesson is simple: **a path is not harmless metadata when the program will read from or write to it.** + +## 41. When not to use raw text files as the whole data model + +Plain text is excellent for simple content, but manually inventing separators and parsing rules becomes fragile as data gains structure. + +For example: + +```text +name|score|date|notes +``` + +raises questions about escaping `|`, missing fields, types, and embedded newlines. + +Chapter 04 introduces TXT, CSV, and JSON so format choice can match the shape of the data instead of forcing every problem into ad-hoc text parsing. + +## 42. Exercise + +Create a small program called `study_notes.py` with these requirements: + +1. Start with three topic names in a list. +2. Open `study_notes.txt` with `"w"` and `encoding="utf-8"`. +3. Write one topic per line. +4. Reopen the file with `"a"` and add one more topic. +5. Reopen it with `"r"` and iterate over the lines. +6. Print each topic without an extra blank line. +7. Use `with` for every file operation. +8. Explain in a comment why `"w"` is appropriate for the first open and `"a"` for the second. + +Stretch questions: + +- What would happen if the first mode were `"x"` and the file already existed? +- Which exception would you expect if you tried to read a missing file? +- Why might `read()` be a poor choice if the file could contain millions of lines? + +## 43. Review checklist + +Before moving on, make sure you can answer these without guessing: + +- What does `open()` return? +- Why is `with open(...)` safer than a manual `open()` / `close()` pair? +- What does `"w"` do to an existing file? +- How is `"a"` different? +- When does `"x"` raise `FileExistsError`? +- Why should UTF-8 often be written as `encoding="utf-8"` explicitly? +- What does `read()` return at end-of-file in text mode? +- Why can iterating over a file be preferable to `readlines()`? +- Does `write()` add `\n` automatically? +- What happens to the file when an exception leaves the `with` body? +- From which directory is a relative path resolved? +- What is the basic difference between text mode and binary mode? + +## 44. Quick reference + +| Need | Pattern | +|---|---| +| Read UTF-8 text | `with open(path, "r", encoding="utf-8") as file:` | +| Replace UTF-8 text | `with open(path, "w", encoding="utf-8") as file:` | +| Append UTF-8 text | `with open(path, "a", encoding="utf-8") as file:` | +| Create only if absent | `with open(path, "x", encoding="utf-8") as file:` | +| Read all remaining text | `file.read()` | +| Read one line | `file.readline()` | +| Process lines incrementally | `for line in file:` | +| Write text | `file.write(text)` | +| Remove only trailing `\n` | `line.rstrip("\n")` | +| Missing required path | `FileNotFoundError` | +| Existing path with `x` | `FileExistsError` | +| General OS I/O category | `OSError` | +| Binary read | `with open(path, "rb") as file:` | + +Default beginner pattern: + +```python +with open(path, "r", encoding="utf-8") as file: + content = file.read() +``` + +Choose the mode according to intent, specify a known text encoding, keep the file lifetime narrow, and catch only failures for which the surrounding code has a real policy. + +## What comes next + +Chapter 03 establishes safe text-file access and resource lifetime. The next chapter, **TXT, CSV, and JSON**, will focus on how data is represented inside files and which parser or writer should own each format boundary. + +```text +exceptions + ↓ +deliberate raising + ↓ +safe file lifetime with open() + with + ↓ +TXT / CSV / JSON formats + ↓ +modules and packages +``` + +## Official references + +- Python 3.14 built-in `open()` documentation: +- Python 3.14 tutorial, Reading and Writing Files: +- Python 3.14 language reference, `with` statement: +- Python 3.14 `io` documentation, Text Encoding: diff --git a/errors-files-and-modules/03-open-and-with/README.pt-BR.md b/errors-files-and-modules/03-open-and-with/README.pt-BR.md new file mode 100644 index 0000000..1914792 --- /dev/null +++ b/errors-files-and-modules/03-open-and-with/README.pt-BR.md @@ -0,0 +1,847 @@ +
+ +# Abrindo Arquivos com Segurança com `open()` e `with` + +[🇺🇸 English](README.md) · [🇧🇷 Português](README.pt-BR.md) · [🇪🇸 Español](README.es.md) + +
+ +[← Voltar para Erros, Arquivos e Módulos](../README.pt-BR.md) · [← Anterior: Levantando Exceções e Criando Exceções Personalizadas](../02-raise-and-custom-exceptions/README.pt-BR.md) + +Programas frequentemente precisam que os dados continuem existindo depois que o processo termina. Um arquivo de texto pode armazenar anotações, configuração, exportações, logs ou resultados intermediários que uma execução futura poderá ler novamente. + +A função embutida `open()` do Python cria um **objeto arquivo** conectado a um arquivo ou a outro recurso semelhante a arquivo. A instrução `with` dá a esse recurso um tempo de vida claro, garantindo seu fechamento mesmo quando o bloco termina por causa de uma exceção. + +Este capítulo se concentra em **arquivos de texto simples e gerenciamento seguro de recursos**. O Capítulo 04 usará essa base para trabalhar com TXT, CSV e JSON como formatos de dados. + +**Tempo estimado de estudo:** 100–130 minutos. + +**Requisito de Python:** Python 3.10 ou mais recente. O comportamento de arquivos ensinado aqui foi verificado na documentação oficial do Python 3.14. + +## Objetivos de aprendizagem + +Ao final deste capítulo, você deverá conseguir: + +- explicar o que `open()` retorna e por que um objeto arquivo é um recurso que deve ser fechado; +- abrir arquivos de texto com modos explícitos e uma codificação explícita; +- explicar as diferenças práticas entre `r`, `w`, `a` e `x`; +- ler um arquivo pequeno inteiro, uma linha ou linhas de forma incremental; +- escrever e acrescentar texto controlando caracteres de nova linha deliberadamente; +- usar `with` para que um arquivo seja fechado tanto em saídas normais quanto excepcionais; +- conectar `with` ao papel de limpeza visto anteriormente com `finally`; +- tratar exceções comuns de arquivos na fronteira apropriada; +- explicar por que caminhos relativos dependem do diretório de trabalho atual; +- evitar truncamento acidental, surpresas de codificação e leituras completas desnecessárias; +- distinguir modo texto de modo binário em nível introdutório; +- escolher um padrão básico seguro para tarefas comuns com arquivos. + +## 1. Arquivos introduzem persistência + +Variáveis vivem na memória enquanto um processo Python está em execução. Quando o processo termina, variáveis locais comuns desaparecem. + +Um arquivo oferece ao programa um lugar para armazenar dados fora desse processo: + +```text +memória do programa + ↓ escrita +arquivo de texto no armazenamento + ↓ leitura posterior +outra execução do programa +``` + +Essa persistência é útil, mas também introduz novas possibilidades de falha: um caminho pode não existir, a permissão pode ser negada, o texto pode usar uma codificação inesperada ou o programa pode abrir um arquivo existente em um modo destrutivo. + +## 2. `open()` retorna um objeto arquivo + +Uma chamada comum em modo texto se parece com isto: + +```python +file = open("notes.txt", "r", encoding="utf-8") +``` + +`open()` não retorna diretamente o texto do arquivo. Ele retorna um **objeto arquivo** que oferece operações como `read()`, iteração, `write()` e `close()`. + +O objeto também acompanha estado, como se está aberto e qual é a posição atual de leitura ou escrita. + +## 3. O modelo simplificado de `open()` + +A função embutida completa possui mais parâmetros, mas um bom modelo para iniciantes é: + +```python +open(file, mode="r", encoding=None) +``` + +Para arquivos de texto, pense em três perguntas antes de abrir qualquer coisa: + +1. **Qual caminho?** +2. **Qual operação é desejada: ler, substituir, acrescentar ou criar somente se não existir?** +3. **Qual codificação de texto o arquivo utiliza?** + +Tornar essas escolhas explícitas é mais seguro do que tratar `open()` como uma operação mágica de "pegar o conteúdo do arquivo". + +## 4. Modo `r`: ler um arquivo existente + +`"r"` significa leitura de texto. Também é o modo padrão quando o argumento de modo é omitido. + +```python +file = open("notes.txt", "r", encoding="utf-8") +``` + +O alvo precisa existir. Se não existir, `open()` levanta `FileNotFoundError`. + +Ser explícito com `"r"` costuma ser útil em código educacional e de aplicação porque a operação pretendida fica imediatamente visível. + +## 5. Modo `w`: escrever e substituir + +`"w"` abre um arquivo de texto para escrita. + +```python +file = open("notes.txt", "w", encoding="utf-8") +``` + +Se o arquivo não existir, ele será criado. Se já existir, seu conteúdo anterior será **truncado** antes da nova escrita. + +Esse comportamento destrutivo torna a escolha do modo uma decisão de correção, não um detalhe cosmético. + +```text +arquivo existente + "w" + ↓ +conteúdo antigo removido + ↓ +novas escritas viram o conteúdo +``` + +## 6. Modo `a`: acrescentar ao final + +`"a"` abre para acréscimo. Novas escritas são colocadas no final em vez de substituir o conteúdo existente. + +```python +with open("notes.txt", "a", encoding="utf-8") as file: + file.write("Files\n") +``` + +Se o arquivo não existir, o modo de acréscimo o cria. + +O modo append é útil quando o conteúdo anterior deve permanecer intacto e cada nova escrita pertence ao final. + +## 7. Modo `x`: criar somente se o arquivo for novo + +`"x"` solicita criação exclusiva. + +```python +with open("notes.txt", "x", encoding="utf-8") as file: + file.write("First version\n") +``` + +Se o caminho já existir, o Python levanta `FileExistsError` em vez de substituí-lo. + +Use esse modo quando sobrescrever acidentalmente um arquivo existente seria um erro. + +## 8. Escolha o modo pela intenção + +Uma tabela compacta de decisão: + +| Intenção | Modo típico | Arquivo existente | +|---|---|---| +| Ler | `r` | mantido | +| Substituir conteúdo | `w` | truncado | +| Acrescentar ao final | `a` | mantido | +| Criar somente se ausente | `x` | levanta `FileExistsError` | + +Existem combinações como `r+`, `w+` e `a+` para leitura e escrita com o mesmo objeto arquivo. Elas são válidas, mas também combinam regras de posição e de modo que iniciantes raramente precisam. + +Prefira o modo mais simples que corresponda ao trabalho real. + +## 9. Modo texto exige uma decisão de codificação + +Arquivos de texto armazenam bytes, enquanto strings Python contêm texto Unicode. Uma **codificação** define como essas duas representações se relacionam. + +```text +str no Python + ↓ codificar +bytes no arquivo + ↓ decodificar +str no Python +``` + +Se `encoding` for omitido, `open()` usa um padrão que depende do ambiente de execução. Isso pode fazer o mesmo código-fonte se comportar de maneira diferente em sistemas distintos. + +Quando o formato é conhecido como UTF-8, declare isso explicitamente: + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + content = file.read() +``` + +## 10. Por que `with` é o padrão normal para arquivos + +Um objeto arquivo usa um recurso do sistema operacional. Ele deve ser fechado quando o programa termina de utilizá-lo. + +O padrão manual funciona: + +```python +file = open("notes.txt", "r", encoding="utf-8") +content = file.read() +file.close() +``` + +Mas existe um problema: se uma exceção ocorrer entre `open()` e `close()`, a chamada final pode nunca executar. + +A solução usual é `with`: + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + content = file.read() +``` + +Quando a execução sai do bloco `with`, o protocolo de gerenciador de contexto do arquivo executa o trabalho de saída necessário e fecha o arquivo. + +## 11. `with` se conecta diretamente a `finally` + +O Capítulo 01 introduziu `finally` para limpeza. Um gerenciador de contexto empacota esse padrão de limpeza em um protocolo reutilizável. + +Conceitualmente: + +```text +adquirir recurso + ↓ +executar bloco + ↓ +liberar recurso +``` + +Mesmo se o bloco levantar uma exceção, o gerenciador de contexto recebe a oportunidade de executar seu trabalho de saída antes que a exceção continue para fora. + +Para objetos arquivo comuns, isso significa fechar o arquivo. `with` **não** significa "ignorar erros de arquivo"; significa "gerenciar o tempo de vida do recurso de forma confiável". + +## 12. O arquivo fica fechado após o bloco + +O nome atribuído por `as file` ainda existe após o bloco, mas o objeto arquivo subjacente está fechado: + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + content = file.read() + +print(file.closed) +``` + +Saída: + +```text +True +``` + +Tentar realizar I/O normal nesse objeto arquivo fechado levanta `ValueError`. + +Não projete código esperando continuar usando o arquivo fora do bloco `with`. Mova os dados necessários para objetos Python comuns. + +## 13. Leia um arquivo pequeno com `read()` + +`read()` sem um argumento de tamanho lê da posição atual até o fim do arquivo. + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + content = file.read() + +print(content) +``` + +Isso é simples e apropriado para um arquivo que sabemos ser pequeno. + +Para um arquivo muito grande ou sem limite conhecido, ler tudo de uma vez pode consumir memória desnecessariamente. Nesse caso, processe o arquivo de forma incremental. + +## 14. `read(size)` avança a posição atual + +Um tamanho positivo solicita no máximo aquela quantidade de caracteres em modo texto: + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + first = file.read(5) + second = file.read(5) +``` + +A segunda chamada continua de onde a primeira parou. Leituras de arquivo mantêm estado. + +No fim do arquivo, outro `read()` em modo texto retorna uma string vazia. + +Esse modelo de posição se torna importante sempre que várias leituras são feitas pelo mesmo objeto arquivo. + +## 15. Leia uma linha com `readline()` + +`readline()` lê uma linha por vez: + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + first_line = file.readline() + second_line = file.readline() +``` + +Quando uma linha termina com uma nova linha no arquivo, esse `\n` normalmente faz parte da string retornada. + +No fim do arquivo, `readline()` retorna `""`. + +Uma linha vazia contendo somente a quebra de linha é `"\n"`, o que é diferente do fim do arquivo. + +## 16. Itere sobre o arquivo para trabalhar por linhas + +Para processamento comum linha por linha, itere sobre o objeto arquivo: + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + for line in file: + print(line, end="") +``` + +Isso evita criar primeiro uma lista contendo todas as linhas e é o padrão simples preferido para processamento incremental por linhas. + +O objeto arquivo é um iterável. O loop consome linhas a partir da posição atual. + +## 17. Seja deliberado ao remover quebras de linha + +Um padrão tentador é: + +```python +clean = line.strip() +``` + +Mas `strip()` remove espaços em branco do início e do fim, não apenas a quebra de linha. Isso pode alterar dados significativos. + +Se a única mudança desejada for remover um caractere de nova linha no final, seja mais específico: + +```python +clean = line.rstrip("\n") +``` + +Remover ou não outros espaços em branco é uma decisão do formato dos dados, não uma regra universal de arquivos. + +## 18. `readlines()` cria uma lista + +`readlines()` retorna as linhas restantes como uma lista: + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + lines = file.readlines() +``` + +Isso pode ser conveniente quando o conjunto completo de linhas é pequeno e você realmente precisa de operações de lista depois. + +Não use automaticamente. Se cada linha puder ser processada de forma independente, iterar sobre o arquivo mantém o uso de memória mais simples e escalável. + +## 19. Escreva texto com `write()` + +Em modo texto, `write()` espera uma string: + +```python +with open("notes.txt", "w", encoding="utf-8") as file: + file.write("Functions\n") + file.write("Exceptions\n") +``` + +`write()` **não** adiciona uma quebra de linha automaticamente. Se o arquivo deve conter quebras de linha, inclua-as explicitamente. + +O método retorna a quantidade de caracteres escritos em modo texto: + +```python +with open("notes.txt", "w", encoding="utf-8") as file: + count = file.write("Python\n") + +print(count) +``` + +## 20. Converta valores não string antes de escrever texto + +`write()` em modo texto não formata objetos Python arbitrários por você: + +```python +score = 92 + +with open("score.txt", "w", encoding="utf-8") as file: + file.write(str(score)) +``` + +Uma f-string costuma ser mais clara quando rótulos ou formatação são necessários: + +```python +with open("score.txt", "w", encoding="utf-8") as file: + file.write(f"score={score}\n") +``` + +O Capítulo 04 introduzirá formatos estruturados que oferecem convenções melhores para armazenar dados mais complexos. + +## 21. `writelines()` não inventa separadores + +`writelines()` escreve strings de um iterável, mas não adiciona caracteres de nova linha entre elas: + +```python +lines = ["Functions\n", "Exceptions\n", "Files\n"] + +with open("notes.txt", "w", encoding="utf-8") as file: + file.writelines(lines) +``` + +Se as strings ainda não contiverem separadores, o resultado ficará concatenado. + +Para iniciantes, chamadas repetidas de `write()` costumam ser mais fáceis de inspecionar até que o formato exato dos dados esteja claro. + +## 22. Caminhos relativos dependem do diretório de trabalho atual + +Um caminho como: + +```python +open("data/notes.txt", "r", encoding="utf-8") +``` + +é **relativo**. O Python o resolve a partir do diretório de trabalho atual do processo, que não é garantido ser o mesmo diretório que contém o arquivo `.py`. + +Isso explica uma surpresa comum para iniciantes: + +```text +mesmo código-fonte ++ diretório de trabalho diferente += caminho resolvido diferente +``` + +Capítulos posteriores introduzirão `pathlib`, que oferece uma API de caminhos mais rica. Por enquanto, saiba sempre de qual diretório seu processo está sendo executado ao usar caminhos relativos. + +## 23. Caminhos absolutos identificam um local a partir da raiz do sistema de arquivos + +Um caminho absoluto não depende do diretório de trabalho atual da mesma maneira. Sua sintaxe exata é específica da plataforma. + +Colocar no código-fonte reutilizável um caminho absoluto fixo de um único computador costuma ser um problema de portabilidade. + +Prefira receber caminhos por configuração, argumentos ou uma estratégia de construção de caminhos apropriada ao programa em vez de embutir no código o layout da máquina de um desenvolvedor. + +## 24. Exceções comuns de arquivos + +Operações de arquivo podem levantar vários tipos úteis de exceção: + +| Exceção | Significado típico | +|---|---| +| `FileNotFoundError` | um caminho necessário não existe | +| `FileExistsError` | criação exclusiva apontou para um caminho existente | +| `PermissionError` | a operação não é permitida | +| `IsADirectoryError` | uma operação de arquivo apontou para um diretório | +| `UnicodeDecodeError` | bytes não puderam ser decodificados com a codificação de texto escolhida | +| `OSError` | falhas mais amplas de I/O do sistema operacional | + +Esses tipos são sinais, não instruções para capturar tudo. Trate uma exceção somente onde o programa possui uma resposta significativa. + +## 25. Coloque `try` ao redor da fronteira que você consegue tratar + +Se um arquivo opcional ausente possui um fallback claro, capture essa falha específica: + +```python +try: + with open("preferences.txt", "r", encoding="utf-8") as file: + preferences = file.read() +except FileNotFoundError: + preferences = "" +``` + +O `with` continua cuidando do fechamento sempre que a abertura é bem-sucedida. + +Um `except OSError:` amplo pode ser apropriado quando várias falhas do sistema operacional realmente possuem a mesma política, mas não deve ser usado apenas para fazer todos os problemas de arquivo desaparecerem. + +## 26. Se o corpo falhar, a limpeza ocorre antes da propagação + +Considere: + +```python +with open("scores.txt", "r", encoding="utf-8") as file: + score = int(file.readline()) +``` + +Se a linha contiver texto inválido para inteiro, `int()` levanta `ValueError`. + +O gerenciador de contexto do arquivo executa seu trabalho de saída enquanto o bloco é encerrado, e a exceção continua para fora a menos que algum código ao redor a trate. + +Essa é a composição principal: + +```text +abertura bem-sucedida + ↓ +corpo levanta exceção + ↓ +arquivo é fechado + ↓ +exceção se propaga +``` + +## 27. Separe acesso ao arquivo da interpretação dos dados quando for útil + +Um desenho útil é deixar uma função ler o texto e outra interpretá-lo: + +```python +def read_text(path: str) -> str: + with open(path, "r", encoding="utf-8") as file: + return file.read() + + +def parse_score(text: str) -> int: + score = int(text) + if not 0 <= score <= 100: + raise ValueError("score must be between 0 and 100") + return score +``` + +Agora falhas de arquivo e falhas de validação do conteúdo são conceitualmente distintas. + +Essa separação se torna especialmente útil no Capítulo 04 ao interpretar dados estruturados. + +## 28. Valide antes de escritas destrutivas quando for prático + +Como `"w"` trunca um arquivo existente quando ele é aberto, valide os dados que puderem ser validados **antes** de abrir o destino em modo de escrita. + +Prefira esta ordem: + +```text +construir ou validar dados de saída + ↓ +abrir destino com "w" + ↓ +escrever texto validado +``` + +em vez de abrir o destino primeiro e somente depois descobrir que os dados são inválidos. + +Isso não torna a escrita atômica nem protege contra todas as falhas possíveis, mas reduz uma classe evitável de perda acidental de dados. + +## 29. Modo texto e modo binário são interfaces diferentes + +Modo texto é o padrão e trabalha com `str`. + +Modo binário adiciona `"b"` ao modo e trabalha com `bytes`: + +```python +with open("image.bin", "rb") as file: + data = file.read() +``` + +Em modo binário, codificação de texto não é usada porque o Python não está convertendo entre `str` e bytes do arquivo. + +Este capítulo se concentra em modo texto. Use modo binário quando o formato dos dados é fundamentalmente bytes, como muitas imagens, arquivos compactados ou payloads de protocolos. + +## 30. Não passe `encoding` em modo binário + +Esta combinação é conceitualmente errada: + +```python +open("data.bin", "rb", encoding="utf-8") +``` + +Modo binário expõe bytes diretamente, então um parâmetro de codificação não faz parte dessa interface. + +Escolha um modelo: + +```text +modo texto → str + encoding +modo binário → bytes +``` + +## 31. Vários gerenciadores de contexto podem compartilhar um `with` + +O Python pode gerenciar mais de um contexto em uma única instrução: + +```python +with ( + open("input.txt", "r", encoding="utf-8") as source, + open("output.txt", "w", encoding="utf-8") as destination, +): + destination.write(source.read()) +``` + +Ambos os recursos recebem seu tratamento de saída correspondente. + +Para iniciantes, instruções `with` aninhadas ou com vários itens são mais úteis quando a operação realmente precisa dos dois recursos ao mesmo tempo. Não abra arquivos antes da hora nem os mantenha abertos por mais tempo do que o necessário. + +## 32. Exemplo prático: escrever e depois ler + +O primeiro exemplo executável cria um diretório temporário apenas para que o teste do repositório exercite I/O real de arquivos sem deixar arquivos gerados para trás. + +```python +import os +import tempfile + + +with tempfile.TemporaryDirectory() as directory: + path = os.path.join(directory, "topics.txt") + + with open(path, "w", encoding="utf-8") as file: + file.write("Functions\n") + file.write("Exceptions\n") + file.write("Files\n") + + with open(path, "r", encoding="utf-8") as file: + for line in file: + print(line.rstrip("\n")) +``` + +Saída: + +```text +Functions +Exceptions +Files +``` + +Os auxiliares `tempfile` e `os.path` servem apenas para organização do exemplo executável. O alvo de aprendizagem do capítulo são os dois blocos `with open(...)`. + +Versão executável: [`examples/write_and_read_text.py`](examples/write_and_read_text.py). + +## 33. Exemplo prático: acrescentar sem substituir + +O segundo exemplo torna visível a diferença entre `"w"` e `"a"`: + +```python +import os +import tempfile + + +with tempfile.TemporaryDirectory() as directory: + path = os.path.join(directory, "history.txt") + + with open(path, "w", encoding="utf-8") as file: + file.write("Chapter 01\n") + + with open(path, "a", encoding="utf-8") as file: + file.write("Chapter 02\n") + file.write("Chapter 03\n") + + with open(path, "r", encoding="utf-8") as file: + print(file.read(), end="") +``` + +Saída: + +```text +Chapter 01 +Chapter 02 +Chapter 03 +``` + +Versão executável: [`examples/append_text.py`](examples/append_text.py). + +## 34. Exemplo prático: tratar um arquivo opcional ausente + +O terceiro exemplo conecta acesso a arquivos ao modelo de exceções dos Capítulos 01 e 02: + +```python +import os +import tempfile + + +with tempfile.TemporaryDirectory() as directory: + path = os.path.join(directory, "optional.txt") + + try: + with open(path, "r", encoding="utf-8") as file: + content = file.read() + except FileNotFoundError: + content = "default settings" + + print(content) +``` + +Saída: + +```text +default settings +``` + +O fallback é significativo porque esse arquivo é explicitamente opcional. Um arquivo obrigatório normalmente precisaria de uma política diferente. + +Versão executável: [`examples/handle_missing_file.py`](examples/handle_missing_file.py). + +## 35. Erro comum: abrir com `w` quando você queria `a` + +Isto substitui o conteúdo anterior: + +```python +with open("history.txt", "w", encoding="utf-8") as file: + file.write("new entry\n") +``` + +Se a intenção era preservar o histórico antigo e adicionar uma entrada, use `"a"`. + +Antes de cada `open()` capaz de escrever, pergunte se o conteúdo existente deve ser substituído, preservado ou protegido contra sobrescrita. + +## 36. Erro comum: esquecer a codificação + +Isto depende da codificação de texto padrão do ambiente: + +```python +with open("notes.txt", "r") as file: + content = file.read() +``` + +Se o formato do arquivo é definido como UTF-8, diga isso: + +```python +with open("notes.txt", "r", encoding="utf-8") as file: + content = file.read() +``` + +Codificação explícita torna a intenção visível e evita uma fonte importante de surpresas entre plataformas. + +## 37. Erro comum: fechamento manual com uma lacuna para exceções + +Isto possui uma lacuna de limpeza: + +```python +file = open("scores.txt", "r", encoding="utf-8") +score = int(file.readline()) +file.close() +``` + +Se `int()` levantar uma exceção, `close()` será pulado. + +Prefira: + +```python +with open("scores.txt", "r", encoding="utf-8") as file: + score = int(file.readline()) +``` + +Agora a limpeza do recurso está ligada ao tempo de vida do bloco. + +## 38. Erro comum: tratar todo problema de arquivo como se fosse igual + +Evite colapsar falhas não relacionadas sem motivo: + +```python +try: + with open("settings.txt", "r", encoding="utf-8") as file: + settings = file.read() +except Exception: + settings = "" +``` + +Isso pode esconder erros de programação e falhas inesperadas. + +Escolha uma exceção específica quando a política de recuperação for específica. Se várias subclasses de `OSError` realmente tiverem a mesma política, documente essa decisão mais ampla. + +## 39. Erro comum: usar `read()` automaticamente para todo arquivo + +Ler o arquivo inteiro é conveniente, não universalmente ideal. + +Se a tarefa é "processar cada linha de forma independente", isto costuma ser melhor: + +```python +with open("events.txt", "r", encoding="utf-8") as file: + for line in file: + process(line) +``` + +do que carregar primeiro todas as linhas em uma string gigante. + +Escolha a estratégia de leitura a partir do tamanho e do modelo de processamento dos dados. + +## 40. Caminhos vindos de usuários são uma fronteira de entrada + +Se um programa aceita um caminho vindo de um usuário, requisição de API, arquivo de configuração ou argumento de linha de comando, esse caminho é entrada. + +Uma operação capaz de escrever pode modificar ou criar dados no local resolvido. + +Aplicações com requisitos de segurança ou proteção de dados devem validar ou limitar os locais permitidos de acordo com sua própria política. A política exata depende do programa e está além deste capítulo introdutório. + +A lição geral é simples: **um caminho não é apenas metadado inofensivo quando o programa vai ler ou escrever nele.** + +## 41. Quando não usar arquivos de texto brutos como todo o modelo de dados + +Texto simples é excelente para conteúdo simples, mas inventar manualmente separadores e regras de parsing se torna frágil conforme os dados ganham estrutura. + +Por exemplo: + +```text +name|score|date|notes +``` + +levanta perguntas sobre escape de `|`, campos ausentes, tipos e quebras de linha embutidas. + +O Capítulo 04 introduz TXT, CSV e JSON para que a escolha do formato corresponda à forma dos dados em vez de forçar todo problema a um parsing de texto improvisado. + +## 42. Exercício + +Crie um pequeno programa chamado `study_notes.py` com estes requisitos: + +1. Comece com três nomes de tópicos em uma lista. +2. Abra `study_notes.txt` com `"w"` e `encoding="utf-8"`. +3. Escreva um tópico por linha. +4. Reabra o arquivo com `"a"` e adicione mais um tópico. +5. Reabra com `"r"` e itere sobre as linhas. +6. Exiba cada tópico sem uma linha em branco extra. +7. Use `with` para toda operação de arquivo. +8. Explique em um comentário por que `"w"` é apropriado na primeira abertura e `"a"` na segunda. + +Perguntas extras: + +- O que aconteceria se o primeiro modo fosse `"x"` e o arquivo já existisse? +- Qual exceção você esperaria ao tentar ler um arquivo ausente? +- Por que `read()` poderia ser uma escolha ruim se o arquivo pudesse conter milhões de linhas? + +## 43. Checklist de revisão + +Antes de seguir, confirme que você consegue responder sem chutar: + +- O que `open()` retorna? +- Por que `with open(...)` é mais seguro do que um par manual `open()` / `close()`? +- O que `"w"` faz com um arquivo existente? +- Como `"a"` é diferente? +- Quando `"x"` levanta `FileExistsError`? +- Por que UTF-8 frequentemente deve ser escrito explicitamente como `encoding="utf-8"`? +- O que `read()` retorna no fim do arquivo em modo texto? +- Por que iterar sobre um arquivo pode ser preferível a `readlines()`? +- `write()` adiciona `\n` automaticamente? +- O que acontece com o arquivo quando uma exceção sai do corpo do `with`? +- A partir de qual diretório um caminho relativo é resolvido? +- Qual é a diferença básica entre modo texto e modo binário? + +## 44. Referência rápida + +| Necessidade | Padrão | +|---|---| +| Ler texto UTF-8 | `with open(path, "r", encoding="utf-8") as file:` | +| Substituir texto UTF-8 | `with open(path, "w", encoding="utf-8") as file:` | +| Acrescentar texto UTF-8 | `with open(path, "a", encoding="utf-8") as file:` | +| Criar somente se ausente | `with open(path, "x", encoding="utf-8") as file:` | +| Ler todo o texto restante | `file.read()` | +| Ler uma linha | `file.readline()` | +| Processar linhas incrementalmente | `for line in file:` | +| Escrever texto | `file.write(text)` | +| Remover somente `\n` final | `line.rstrip("\n")` | +| Caminho necessário ausente | `FileNotFoundError` | +| Caminho existente com `x` | `FileExistsError` | +| Categoria geral de I/O do SO | `OSError` | +| Leitura binária | `with open(path, "rb") as file:` | + +Padrão inicial recomendado: + +```python +with open(path, "r", encoding="utf-8") as file: + content = file.read() +``` + +Escolha o modo de acordo com a intenção, especifique uma codificação de texto conhecida, mantenha o tempo de vida do arquivo curto e capture somente falhas para as quais o código ao redor possui uma política real. + +## O que vem depois + +O Capítulo 03 estabelece acesso seguro a arquivos de texto e tempo de vida de recursos. O próximo capítulo, **TXT, CSV e JSON**, se concentrará em como os dados são representados dentro dos arquivos e qual parser ou escritor deve ser responsável por cada fronteira de formato. + +```text +exceções + ↓ +levantamento deliberado + ↓ +tempo de vida seguro com open() + with + ↓ +formatos TXT / CSV / JSON + ↓ +módulos e pacotes +``` + +## Referências oficiais + +- Documentação do Python 3.14 para `open()` embutido: +- Tutorial do Python 3.14, Reading and Writing Files: +- Referência da linguagem Python 3.14, instrução `with`: +- Documentação `io` do Python 3.14, Text Encoding: diff --git a/errors-files-and-modules/03-open-and-with/examples/append_text.py b/errors-files-and-modules/03-open-and-with/examples/append_text.py new file mode 100644 index 0000000..2915273 --- /dev/null +++ b/errors-files-and-modules/03-open-and-with/examples/append_text.py @@ -0,0 +1,16 @@ +import os +import tempfile + + +with tempfile.TemporaryDirectory() as directory: + path = os.path.join(directory, "history.txt") + + with open(path, "w", encoding="utf-8") as file: + file.write("Chapter 01\n") + + with open(path, "a", encoding="utf-8") as file: + file.write("Chapter 02\n") + file.write("Chapter 03\n") + + with open(path, "r", encoding="utf-8") as file: + print(file.read(), end="") diff --git a/errors-files-and-modules/03-open-and-with/examples/handle_missing_file.py b/errors-files-and-modules/03-open-and-with/examples/handle_missing_file.py new file mode 100644 index 0000000..d91c487 --- /dev/null +++ b/errors-files-and-modules/03-open-and-with/examples/handle_missing_file.py @@ -0,0 +1,14 @@ +import os +import tempfile + + +with tempfile.TemporaryDirectory() as directory: + path = os.path.join(directory, "optional.txt") + + try: + with open(path, "r", encoding="utf-8") as file: + content = file.read() + except FileNotFoundError: + content = "default settings" + + print(content) diff --git a/errors-files-and-modules/03-open-and-with/examples/write_and_read_text.py b/errors-files-and-modules/03-open-and-with/examples/write_and_read_text.py new file mode 100644 index 0000000..578221e --- /dev/null +++ b/errors-files-and-modules/03-open-and-with/examples/write_and_read_text.py @@ -0,0 +1,15 @@ +import os +import tempfile + + +with tempfile.TemporaryDirectory() as directory: + path = os.path.join(directory, "topics.txt") + + with open(path, "w", encoding="utf-8") as file: + file.write("Functions\n") + file.write("Exceptions\n") + file.write("Files\n") + + with open(path, "r", encoding="utf-8") as file: + for line in file: + print(line.rstrip("\n")) diff --git a/errors-files-and-modules/README.es.md b/errors-files-and-modules/README.es.md index b27b180..044068c 100644 --- a/errors-files-and-modules/README.es.md +++ b/errors-files-and-modules/README.es.md @@ -16,7 +16,7 @@ La Fase 7 comienza con el manejo de excepciones, continúa con la generación de |---|---|---|---| | [01. `try`, `except`, `else` y `finally`](01-try-except-else-finally/README.es.md) | Manejar fallos esperados en runtime manteniendo explícitas las rutas normal y de limpieza | Principiante a intermedio | Disponible | | [02. Lanzar Excepciones y Excepciones Personalizadas](02-raise-and-custom-exceptions/README.es.md) | Señalar estados inválidos deliberadamente con `raise`, volver a lanzar o encadenar fallos de forma intencional e introducir excepciones personalizadas simples | Intermedio | Disponible | -| 03. `open()` y `with` | Leer y escribir archivos de texto gestionando recursos de forma segura | Principiante a intermedio | Planificado | +| [03. `open()` y `with`](03-open-and-with/README.es.md) | Abrir, leer, escribir y añadir a archivos de texto gestionando recursos de forma segura con `with` | Principiante a intermedio | Disponible | | 04. TXT, CSV y JSON | Trabajar con formatos comunes de datos basados en texto y sus límites | Intermedio | Planificado | | 05. Imports, Módulos y Paquetes | Dividir código en archivos reutilizables y comprender el modelo de importación de Python | Intermedio | Planificado | @@ -67,9 +67,9 @@ Al final de la Fase 7, deberías poder: ## Capítulo actual -Continúa con [Lanzar Excepciones y Crear Excepciones Personalizadas](02-raise-and-custom-exceptions/README.es.md). +Continúa con [Abrir Archivos de Forma Segura con `open()` y `with`](03-open-and-with/README.es.md). -El Capítulo 01 establece **el manejo de excepciones que ya ocurren**. El Capítulo 02 añade `raise` deliberado, elección entre tipos built-in y personalizados, relanzamiento con `raise` sin expresión, encadenamiento explícito de excepciones y la distinción entre `raise` y `assert`. El próximo capítulo planificado es **`open()` y `with`**. +Los Capítulos 01–02 establecen manejo y señalización deliberada de excepciones. El Capítulo 03 añade apertura de archivos de texto, encoding explícito, modos de archivo, lectura, escritura, append, errores de archivo específicos y limpieza gestionada por contexto. El próximo capítulo planificado es **TXT, CSV y JSON**. ## Estructura del directorio @@ -86,14 +86,22 @@ errors-files-and-modules/ │ ├── parse_integer.py │ ├── safe_divide.py │ └── trace_try_else_finally.py -└── 02-raise-and-custom-exceptions/ +├── 02-raise-and-custom-exceptions/ +│ ├── README.md +│ ├── README.pt-BR.md +│ ├── README.es.md +│ └── examples/ +│ ├── custom_exception.py +│ ├── exception_chaining.py +│ └── validate_score.py +└── 03-open-and-with/ ├── README.md ├── README.pt-BR.md ├── README.es.md └── examples/ - ├── custom_exception.py - ├── exception_chaining.py - └── validate_score.py + ├── append_text.py + ├── handle_missing_file.py + └── write_and_read_text.py ``` Los directorios de capítulos planificados se añaden únicamente cuando su contenido se publica realmente. diff --git a/errors-files-and-modules/README.md b/errors-files-and-modules/README.md index 50d6099..67add40 100644 --- a/errors-files-and-modules/README.md +++ b/errors-files-and-modules/README.md @@ -16,7 +16,7 @@ Phase 7 starts with exception handling, then moves into deliberately raising exc |---|---|---|---| | [01. `try`, `except`, `else`, and `finally`](01-try-except-else-finally/README.md) | Handle expected runtime failures while keeping normal and cleanup paths explicit | Beginner to intermediate | Available | | [02. Raising and Custom Exceptions](02-raise-and-custom-exceptions/README.md) | Signal invalid states deliberately with `raise`, re-raise or chain failures deliberately, and introduce simple custom exceptions | Intermediate | Available | -| 03. `open()` and `with` | Read and write text files while managing resources safely | Beginner to intermediate | Planned | +| [03. `open()` and `with`](03-open-and-with/README.md) | Open, read, write, and append text files while managing file resources safely with `with` | Beginner to intermediate | Available | | 04. TXT, CSV, and JSON | Work with common text-based data formats and their boundaries | Intermediate | Planned | | 05. Imports, Modules, and Packages | Split code into reusable files and understand Python's import model | Intermediate | Planned | @@ -67,9 +67,9 @@ By the end of Phase 7, you should be able to: ## Current chapter -Continue with [Raising and Custom Exceptions](02-raise-and-custom-exceptions/README.md). +Continue with [Opening Files Safely with `open()` and `with`](03-open-and-with/README.md). -Chapter 01 establishes **handling exceptions that already occur**. Chapter 02 adds deliberate `raise`, choosing built-in versus custom exception types, bare re-raising, explicit exception chaining, and the distinction between `raise` and `assert`. The next planned chapter is **`open()` and `with`**. +Chapters 01–02 establish exception handling and deliberate exception signaling. Chapter 03 adds text-file opening, explicit encodings, file modes, reading, writing, appending, focused file errors, and context-managed cleanup. The next planned chapter is **TXT, CSV, and JSON**. ## Directory structure @@ -86,14 +86,22 @@ errors-files-and-modules/ │ ├── parse_integer.py │ ├── safe_divide.py │ └── trace_try_else_finally.py -└── 02-raise-and-custom-exceptions/ +├── 02-raise-and-custom-exceptions/ +│ ├── README.md +│ ├── README.pt-BR.md +│ ├── README.es.md +│ └── examples/ +│ ├── custom_exception.py +│ ├── exception_chaining.py +│ └── validate_score.py +└── 03-open-and-with/ ├── README.md ├── README.pt-BR.md ├── README.es.md └── examples/ - ├── custom_exception.py - ├── exception_chaining.py - └── validate_score.py + ├── append_text.py + ├── handle_missing_file.py + └── write_and_read_text.py ``` Planned chapter directories are added only when their content is actually published. diff --git a/errors-files-and-modules/README.pt-BR.md b/errors-files-and-modules/README.pt-BR.md index 03905a1..4a0f99c 100644 --- a/errors-files-and-modules/README.pt-BR.md +++ b/errors-files-and-modules/README.pt-BR.md @@ -16,7 +16,7 @@ A Fase 7 começa com tratamento de exceções, avança para a criação delibera |---|---|---|---| | [01. `try`, `except`, `else` e `finally`](01-try-except-else-finally/README.pt-BR.md) | Tratar falhas esperadas em runtime mantendo explícitos os caminhos normal e de limpeza | Iniciante a intermediário | Disponível | | [02. Levantando Exceções e Exceções Personalizadas](02-raise-and-custom-exceptions/README.pt-BR.md) | Sinalizar estados inválidos deliberadamente com `raise`, relançar ou encadear falhas de forma intencional e introduzir exceções personalizadas simples | Intermediário | Disponível | -| 03. `open()` e `with` | Ler e escrever arquivos de texto gerenciando recursos com segurança | Iniciante a intermediário | Planejado | +| [03. `open()` e `with`](03-open-and-with/README.pt-BR.md) | Abrir, ler, escrever e acrescentar em arquivos de texto gerenciando recursos com segurança usando `with` | Iniciante a intermediário | Disponível | | 04. TXT, CSV e JSON | Trabalhar com formatos comuns de dados baseados em texto e seus limites | Intermediário | Planejado | | 05. Imports, Módulos e Pacotes | Dividir código em arquivos reutilizáveis e entender o modelo de importação do Python | Intermediário | Planejado | @@ -67,9 +67,9 @@ Ao final da Fase 7, você deverá conseguir: ## Capítulo atual -Continue com [Levantando Exceções e Criando Exceções Personalizadas](02-raise-and-custom-exceptions/README.pt-BR.md). +Continue com [Abrindo Arquivos com Segurança com `open()` e `with`](03-open-and-with/README.pt-BR.md). -O Capítulo 01 estabelece **o tratamento de exceções que já acontecem**. O Capítulo 02 acrescenta `raise` deliberado, escolha entre tipos built-in e personalizados, relançamento com `raise` sem expressão, encadeamento explícito de exceções e a distinção entre `raise` e `assert`. O próximo capítulo planejado é **`open()` e `with`**. +Os Capítulos 01–02 estabelecem tratamento e sinalização deliberada de exceções. O Capítulo 03 acrescenta abertura de arquivos de texto, encoding explícito, modos de arquivo, leitura, escrita, append, erros de arquivo específicos e limpeza gerenciada por contexto. O próximo capítulo planejado é **TXT, CSV e JSON**. ## Estrutura do diretório @@ -86,14 +86,22 @@ errors-files-and-modules/ │ ├── parse_integer.py │ ├── safe_divide.py │ └── trace_try_else_finally.py -└── 02-raise-and-custom-exceptions/ +├── 02-raise-and-custom-exceptions/ +│ ├── README.md +│ ├── README.pt-BR.md +│ ├── README.es.md +│ └── examples/ +│ ├── custom_exception.py +│ ├── exception_chaining.py +│ └── validate_score.py +└── 03-open-and-with/ ├── README.md ├── README.pt-BR.md ├── README.es.md └── examples/ - ├── custom_exception.py - ├── exception_chaining.py - └── validate_score.py + ├── append_text.py + ├── handle_missing_file.py + └── write_and_read_text.py ``` Os diretórios dos capítulos planejados são adicionados somente quando seu conteúdo é realmente publicado. diff --git a/scripts/example_manifest.txt b/scripts/example_manifest.txt index febce99..bee7f65 100644 --- a/scripts/example_manifest.txt +++ b/scripts/example_manifest.txt @@ -111,3 +111,6 @@ errors-files-and-modules/01-try-except-else-finally/examples/trace_try_else_fina errors-files-and-modules/02-raise-and-custom-exceptions/examples/custom_exception.py errors-files-and-modules/02-raise-and-custom-exceptions/examples/exception_chaining.py errors-files-and-modules/02-raise-and-custom-exceptions/examples/validate_score.py +errors-files-and-modules/03-open-and-with/examples/append_text.py +errors-files-and-modules/03-open-and-with/examples/handle_missing_file.py +errors-files-and-modules/03-open-and-with/examples/write_and_read_text.py