nia-etl-utils 0.1.0__py3-none-any.whl → 0.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nia_etl_utils/__init__.py +173 -43
- nia_etl_utils/config.py +391 -0
- nia_etl_utils/database.py +249 -153
- nia_etl_utils/email_smtp.py +201 -67
- nia_etl_utils/env_config.py +137 -15
- nia_etl_utils/exceptions.py +394 -0
- nia_etl_utils/limpeza_pastas.py +192 -59
- nia_etl_utils/logger_config.py +98 -40
- nia_etl_utils/ocr.py +401 -0
- nia_etl_utils/processa_csv.py +257 -114
- nia_etl_utils/processa_csv_paralelo.py +150 -37
- nia_etl_utils/results.py +304 -0
- nia_etl_utils-0.2.1.dist-info/METADATA +723 -0
- nia_etl_utils-0.2.1.dist-info/RECORD +16 -0
- {nia_etl_utils-0.1.0.dist-info → nia_etl_utils-0.2.1.dist-info}/WHEEL +1 -1
- nia_etl_utils-0.1.0.dist-info/METADATA +0 -594
- nia_etl_utils-0.1.0.dist-info/RECORD +0 -12
- {nia_etl_utils-0.1.0.dist-info → nia_etl_utils-0.2.1.dist-info}/top_level.txt +0 -0
nia_etl_utils/limpeza_pastas.py
CHANGED
|
@@ -1,12 +1,35 @@
|
|
|
1
|
-
"""Funções utilitárias para manipulação de arquivos e diretórios.
|
|
2
|
-
|
|
1
|
+
"""Funções utilitárias para manipulação de arquivos e diretórios.
|
|
2
|
+
|
|
3
|
+
Fornece operações comuns de sistema de arquivos com logging
|
|
4
|
+
apropriado e tratamento de erros consistente.
|
|
5
|
+
|
|
6
|
+
Examples:
|
|
7
|
+
Limpar pasta antes de processamento:
|
|
8
|
+
|
|
9
|
+
>>> from nia_etl_utils import limpar_pasta
|
|
10
|
+
>>> limpar_pasta("/tmp/meu_pipeline")
|
|
11
|
+
|
|
12
|
+
Criar estrutura de diretórios:
|
|
13
|
+
|
|
14
|
+
>>> from nia_etl_utils import criar_pasta_se_nao_existir
|
|
15
|
+
>>> criar_pasta_se_nao_existir("/dados/processados/2025/01")
|
|
16
|
+
|
|
17
|
+
Remover pasta temporária:
|
|
18
|
+
|
|
19
|
+
>>> from nia_etl_utils import remover_pasta_recursivamente
|
|
20
|
+
>>> remover_pasta_recursivamente("/tmp/pasta_temporaria")
|
|
21
|
+
"""
|
|
22
|
+
|
|
3
23
|
import shutil
|
|
4
24
|
from pathlib import Path
|
|
25
|
+
|
|
5
26
|
from loguru import logger
|
|
6
27
|
|
|
28
|
+
from .exceptions import DiretorioError
|
|
29
|
+
|
|
7
30
|
|
|
8
|
-
def limpar_pasta(pasta: str, log: bool = True) ->
|
|
9
|
-
"""Remove todos os arquivos de uma pasta,
|
|
31
|
+
def limpar_pasta(pasta: str, log: bool = True) -> int:
|
|
32
|
+
"""Remove todos os arquivos de uma pasta, preservando subdiretórios.
|
|
10
33
|
|
|
11
34
|
Se a pasta não existir, ela será criada. Se existir, todos os arquivos
|
|
12
35
|
dentro dela serão removidos (subdiretórios são preservados).
|
|
@@ -15,13 +38,22 @@ def limpar_pasta(pasta: str, log: bool = True) -> None:
|
|
|
15
38
|
pasta: Caminho da pasta que será limpa.
|
|
16
39
|
log: Se True, emite logs com Loguru. Defaults to True.
|
|
17
40
|
|
|
41
|
+
Returns:
|
|
42
|
+
Número de arquivos removidos.
|
|
43
|
+
|
|
18
44
|
Raises:
|
|
19
|
-
|
|
45
|
+
DiretorioError: Se houver erro ao criar ou limpar a pasta.
|
|
20
46
|
|
|
21
47
|
Examples:
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
>>>
|
|
48
|
+
Limpar pasta de saída antes de processamento:
|
|
49
|
+
|
|
50
|
+
>>> from nia_etl_utils import limpar_pasta
|
|
51
|
+
>>> removidos = limpar_pasta("/tmp/meu_pipeline")
|
|
52
|
+
>>> print(f"{removidos} arquivo(s) removido(s)")
|
|
53
|
+
|
|
54
|
+
Limpar sem logging:
|
|
55
|
+
|
|
56
|
+
>>> limpar_pasta("/tmp/dados", log=False)
|
|
25
57
|
"""
|
|
26
58
|
try:
|
|
27
59
|
pasta_path = Path(pasta)
|
|
@@ -30,46 +62,66 @@ def limpar_pasta(pasta: str, log: bool = True) -> None:
|
|
|
30
62
|
pasta_path.mkdir(parents=True, exist_ok=True)
|
|
31
63
|
if log:
|
|
32
64
|
logger.info(f"Pasta criada: {pasta}")
|
|
33
|
-
|
|
34
|
-
arquivos_removidos = 0
|
|
65
|
+
return 0
|
|
35
66
|
|
|
36
|
-
|
|
37
|
-
if item.is_file():
|
|
38
|
-
item.unlink()
|
|
39
|
-
arquivos_removidos += 1
|
|
40
|
-
if log:
|
|
41
|
-
logger.debug(f"Arquivo removido: {item}")
|
|
67
|
+
arquivos_removidos = 0
|
|
42
68
|
|
|
43
|
-
|
|
44
|
-
|
|
69
|
+
for item in pasta_path.iterdir():
|
|
70
|
+
if item.is_file():
|
|
71
|
+
item.unlink()
|
|
72
|
+
arquivos_removidos += 1
|
|
73
|
+
if log:
|
|
74
|
+
logger.debug(f"Arquivo removido: {item}")
|
|
45
75
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
sys.exit(1)
|
|
52
|
-
except Exception as error:
|
|
53
|
-
logger.error(f"Erro inesperado ao limpar a pasta '{pasta}': {error}")
|
|
54
|
-
sys.exit(1)
|
|
76
|
+
if log:
|
|
77
|
+
logger.info(
|
|
78
|
+
f"Pasta '{pasta}' limpa com sucesso. "
|
|
79
|
+
f"{arquivos_removidos} arquivo(s) removido(s)."
|
|
80
|
+
)
|
|
55
81
|
|
|
82
|
+
return arquivos_removidos
|
|
56
83
|
|
|
57
|
-
|
|
84
|
+
except PermissionError as e:
|
|
85
|
+
raise DiretorioError(
|
|
86
|
+
f"Sem permissão para acessar/modificar a pasta '{pasta}'",
|
|
87
|
+
details={"pasta": pasta, "erro": str(e)}
|
|
88
|
+
) from e
|
|
89
|
+
except OSError as e:
|
|
90
|
+
raise DiretorioError(
|
|
91
|
+
f"Erro do sistema ao manipular a pasta '{pasta}'",
|
|
92
|
+
details={"pasta": pasta, "erro": str(e)}
|
|
93
|
+
) from e
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def remover_pasta_recursivamente(pasta: str, log: bool = True) -> bool:
|
|
58
97
|
"""Remove uma pasta e todo seu conteúdo (arquivos e subpastas).
|
|
59
98
|
|
|
60
|
-
ATENÇÃO: Esta função remove TUDO dentro da pasta, incluindo
|
|
61
|
-
Use com cautela.
|
|
99
|
+
ATENÇÃO: Esta função remove TUDO dentro da pasta, incluindo
|
|
100
|
+
subdiretórios. Use com cautela.
|
|
62
101
|
|
|
63
102
|
Args:
|
|
64
103
|
pasta: Caminho da pasta que será removida completamente.
|
|
65
104
|
log: Se True, emite logs com Loguru. Defaults to True.
|
|
66
105
|
|
|
106
|
+
Returns:
|
|
107
|
+
True se a pasta foi removida, False se não existia.
|
|
108
|
+
|
|
67
109
|
Raises:
|
|
68
|
-
|
|
110
|
+
DiretorioError: Se o caminho não for um diretório ou
|
|
111
|
+
houver erro ao remover.
|
|
69
112
|
|
|
70
113
|
Examples:
|
|
71
|
-
|
|
72
|
-
|
|
114
|
+
Remover pasta temporária:
|
|
115
|
+
|
|
116
|
+
>>> from nia_etl_utils import remover_pasta_recursivamente
|
|
117
|
+
>>> if remover_pasta_recursivamente("/tmp/pasta_temporaria"):
|
|
118
|
+
... print("Pasta removida")
|
|
119
|
+
... else:
|
|
120
|
+
... print("Pasta não existia")
|
|
121
|
+
|
|
122
|
+
Remover sem logging:
|
|
123
|
+
|
|
124
|
+
>>> remover_pasta_recursivamente("/tmp/dados", log=False)
|
|
73
125
|
"""
|
|
74
126
|
try:
|
|
75
127
|
pasta_path = Path(pasta)
|
|
@@ -77,41 +129,58 @@ def remover_pasta_recursivamente(pasta: str, log: bool = True) -> None:
|
|
|
77
129
|
if not pasta_path.exists():
|
|
78
130
|
if log:
|
|
79
131
|
logger.warning(f"Pasta '{pasta}' não existe. Nada a remover.")
|
|
80
|
-
return
|
|
132
|
+
return False
|
|
81
133
|
|
|
82
134
|
if not pasta_path.is_dir():
|
|
83
|
-
|
|
84
|
-
|
|
135
|
+
raise DiretorioError(
|
|
136
|
+
f"'{pasta}' não é um diretório",
|
|
137
|
+
details={"pasta": pasta, "tipo": "arquivo"}
|
|
138
|
+
)
|
|
85
139
|
|
|
86
140
|
shutil.rmtree(pasta_path)
|
|
87
141
|
|
|
88
142
|
if log:
|
|
89
143
|
logger.info(f"Pasta '{pasta}' removida completamente (incluindo subpastas).")
|
|
90
144
|
|
|
91
|
-
|
|
92
|
-
logger.error(f"Sem permissão para remover a pasta '{pasta}': {error}")
|
|
93
|
-
sys.exit(1)
|
|
94
|
-
except OSError as error:
|
|
95
|
-
logger.error(f"Erro do sistema ao remover a pasta '{pasta}': {error}")
|
|
96
|
-
sys.exit(1)
|
|
97
|
-
except Exception as error:
|
|
98
|
-
logger.error(f"Erro inesperado ao remover a pasta '{pasta}': {error}")
|
|
99
|
-
sys.exit(1)
|
|
145
|
+
return True
|
|
100
146
|
|
|
147
|
+
except PermissionError as e:
|
|
148
|
+
raise DiretorioError(
|
|
149
|
+
f"Sem permissão para remover a pasta '{pasta}'",
|
|
150
|
+
details={"pasta": pasta, "erro": str(e)}
|
|
151
|
+
) from e
|
|
152
|
+
except OSError as e:
|
|
153
|
+
raise DiretorioError(
|
|
154
|
+
f"Erro do sistema ao remover a pasta '{pasta}'",
|
|
155
|
+
details={"pasta": pasta, "erro": str(e)}
|
|
156
|
+
) from e
|
|
101
157
|
|
|
102
|
-
|
|
158
|
+
|
|
159
|
+
def criar_pasta_se_nao_existir(pasta: str, log: bool = True) -> bool:
|
|
103
160
|
"""Cria uma pasta se ela não existir (incluindo pastas pai).
|
|
104
161
|
|
|
105
162
|
Args:
|
|
106
163
|
pasta: Caminho da pasta que será criada.
|
|
107
164
|
log: Se True, emite logs com Loguru. Defaults to True.
|
|
108
165
|
|
|
166
|
+
Returns:
|
|
167
|
+
True se a pasta foi criada, False se já existia.
|
|
168
|
+
|
|
109
169
|
Raises:
|
|
110
|
-
|
|
170
|
+
DiretorioError: Se houver erro ao criar a pasta.
|
|
111
171
|
|
|
112
172
|
Examples:
|
|
113
|
-
|
|
114
|
-
|
|
173
|
+
Criar estrutura de diretórios:
|
|
174
|
+
|
|
175
|
+
>>> from nia_etl_utils import criar_pasta_se_nao_existir
|
|
176
|
+
>>> if criar_pasta_se_nao_existir("/tmp/dados/processados/2025"):
|
|
177
|
+
... print("Estrutura criada")
|
|
178
|
+
... else:
|
|
179
|
+
... print("Já existia")
|
|
180
|
+
|
|
181
|
+
Criar sem logging:
|
|
182
|
+
|
|
183
|
+
>>> criar_pasta_se_nao_existir("/tmp/dados", log=False)
|
|
115
184
|
"""
|
|
116
185
|
try:
|
|
117
186
|
pasta_path = Path(pasta)
|
|
@@ -119,19 +188,83 @@ def criar_pasta_se_nao_existir(pasta: str, log: bool = True) -> None:
|
|
|
119
188
|
if pasta_path.exists():
|
|
120
189
|
if log:
|
|
121
190
|
logger.debug(f"Pasta '{pasta}' já existe.")
|
|
122
|
-
return
|
|
191
|
+
return False
|
|
123
192
|
|
|
124
193
|
pasta_path.mkdir(parents=True, exist_ok=True)
|
|
125
194
|
|
|
126
195
|
if log:
|
|
127
196
|
logger.info(f"Pasta criada: {pasta}")
|
|
128
197
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
198
|
+
return True
|
|
199
|
+
|
|
200
|
+
except PermissionError as e:
|
|
201
|
+
raise DiretorioError(
|
|
202
|
+
f"Sem permissão para criar a pasta '{pasta}'",
|
|
203
|
+
details={"pasta": pasta, "erro": str(e)}
|
|
204
|
+
) from e
|
|
205
|
+
except OSError as e:
|
|
206
|
+
raise DiretorioError(
|
|
207
|
+
f"Erro do sistema ao criar a pasta '{pasta}'",
|
|
208
|
+
details={"pasta": pasta, "erro": str(e)}
|
|
209
|
+
) from e
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def listar_arquivos(
|
|
213
|
+
pasta: str,
|
|
214
|
+
extensao: str | None = None,
|
|
215
|
+
recursivo: bool = False
|
|
216
|
+
) -> list[Path]:
|
|
217
|
+
"""Lista arquivos em uma pasta.
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
pasta: Caminho da pasta a ser listada.
|
|
221
|
+
extensao: Filtrar por extensão (ex: ".csv", ".json").
|
|
222
|
+
Se None, lista todos os arquivos.
|
|
223
|
+
recursivo: Se True, inclui arquivos em subpastas.
|
|
224
|
+
|
|
225
|
+
Returns:
|
|
226
|
+
Lista de objetos Path para cada arquivo encontrado.
|
|
227
|
+
|
|
228
|
+
Raises:
|
|
229
|
+
DiretorioError: Se a pasta não existir ou não for acessível.
|
|
230
|
+
|
|
231
|
+
Examples:
|
|
232
|
+
Listar todos os CSVs:
|
|
233
|
+
|
|
234
|
+
>>> arquivos = listar_arquivos("/tmp/dados", extensao=".csv")
|
|
235
|
+
>>> for arq in arquivos:
|
|
236
|
+
... print(arq.name)
|
|
237
|
+
|
|
238
|
+
Listar recursivamente:
|
|
239
|
+
|
|
240
|
+
>>> arquivos = listar_arquivos("/tmp/dados", recursivo=True)
|
|
241
|
+
"""
|
|
242
|
+
try:
|
|
243
|
+
pasta_path = Path(pasta)
|
|
244
|
+
|
|
245
|
+
if not pasta_path.exists():
|
|
246
|
+
raise DiretorioError(
|
|
247
|
+
f"Pasta '{pasta}' não existe",
|
|
248
|
+
details={"pasta": pasta}
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
if not pasta_path.is_dir():
|
|
252
|
+
raise DiretorioError(
|
|
253
|
+
f"'{pasta}' não é um diretório",
|
|
254
|
+
details={"pasta": pasta}
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
if recursivo:
|
|
258
|
+
pattern = "**/*" if extensao is None else f"**/*{extensao}"
|
|
259
|
+
arquivos = [p for p in pasta_path.glob(pattern) if p.is_file()]
|
|
260
|
+
else:
|
|
261
|
+
pattern = "*" if extensao is None else f"*{extensao}"
|
|
262
|
+
arquivos = [p for p in pasta_path.glob(pattern) if p.is_file()]
|
|
263
|
+
|
|
264
|
+
return sorted(arquivos)
|
|
265
|
+
|
|
266
|
+
except PermissionError as e:
|
|
267
|
+
raise DiretorioError(
|
|
268
|
+
f"Sem permissão para acessar a pasta '{pasta}'",
|
|
269
|
+
details={"pasta": pasta, "erro": str(e)}
|
|
270
|
+
) from e
|
nia_etl_utils/logger_config.py
CHANGED
|
@@ -1,8 +1,39 @@
|
|
|
1
|
-
"""Módulo utilitário para configuração de logging com Loguru.
|
|
2
|
-
|
|
1
|
+
"""Módulo utilitário para configuração de logging com Loguru.
|
|
2
|
+
|
|
3
|
+
Fornece funções para configurar o logger com rotação automática,
|
|
4
|
+
retenção configurável e estrutura de diretórios organizada.
|
|
5
|
+
|
|
6
|
+
Examples:
|
|
7
|
+
Configuração básica:
|
|
8
|
+
|
|
9
|
+
>>> from nia_etl_utils import configurar_logger
|
|
10
|
+
>>> caminho = configurar_logger("extract", "2025_01_20")
|
|
11
|
+
>>> logger.info("Pipeline iniciado")
|
|
12
|
+
|
|
13
|
+
Configuração com padrões NIA:
|
|
14
|
+
|
|
15
|
+
>>> from nia_etl_utils import configurar_logger_padrao_nia
|
|
16
|
+
>>> caminho = configurar_logger_padrao_nia("ouvidorias_etl")
|
|
17
|
+
|
|
18
|
+
Configuração customizada:
|
|
19
|
+
|
|
20
|
+
>>> caminho = configurar_logger(
|
|
21
|
+
... prefixo="etl_vendas",
|
|
22
|
+
... data_extracao="2025_01_20",
|
|
23
|
+
... pasta_logs="/var/log/nia",
|
|
24
|
+
... rotation="50 MB",
|
|
25
|
+
... retention="30 days",
|
|
26
|
+
... level="INFO"
|
|
27
|
+
... )
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
from datetime import datetime
|
|
3
31
|
from pathlib import Path
|
|
32
|
+
|
|
4
33
|
from loguru import logger
|
|
5
34
|
|
|
35
|
+
from .exceptions import DiretorioError, ValidacaoError
|
|
36
|
+
|
|
6
37
|
|
|
7
38
|
def configurar_logger(
|
|
8
39
|
prefixo: str,
|
|
@@ -14,32 +45,43 @@ def configurar_logger(
|
|
|
14
45
|
) -> str:
|
|
15
46
|
"""Configura o logger da aplicação com Loguru.
|
|
16
47
|
|
|
17
|
-
Cria um handler de arquivo para o logger com rotação automática
|
|
18
|
-
configurável. O arquivo de log é criado em uma estrutura
|
|
19
|
-
organizada por prefixo.
|
|
48
|
+
Cria um handler de arquivo para o logger com rotação automática
|
|
49
|
+
e retenção configurável. O arquivo de log é criado em uma estrutura
|
|
50
|
+
de diretórios organizada por prefixo.
|
|
20
51
|
|
|
21
52
|
Args:
|
|
22
53
|
prefixo: Nome do módulo/pipeline (ex: 'extract', 'transform', 'load').
|
|
54
|
+
Usado para criar subdiretório e nomear arquivo.
|
|
23
55
|
data_extracao: Data usada no nome do arquivo de log (ex: '2025_01_19').
|
|
24
|
-
pasta_logs: Diretório raiz onde os logs serão armazenados.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
56
|
+
pasta_logs: Diretório raiz onde os logs serão armazenados.
|
|
57
|
+
Defaults to "logs".
|
|
58
|
+
rotation: Critério de rotação do arquivo. Pode ser tamanho
|
|
59
|
+
("10 MB", "500 KB") ou tempo ("1 day", "1 week").
|
|
60
|
+
Defaults to "10 MB".
|
|
61
|
+
retention: Tempo de retenção dos logs antigos antes de serem
|
|
62
|
+
removidos. Defaults to "7 days".
|
|
63
|
+
level: Nível mínimo de log a ser registrado. Opções: DEBUG,
|
|
64
|
+
INFO, WARNING, ERROR, CRITICAL. Defaults to "DEBUG".
|
|
28
65
|
|
|
29
66
|
Returns:
|
|
30
|
-
|
|
67
|
+
Caminho completo do arquivo de log criado.
|
|
31
68
|
|
|
32
69
|
Raises:
|
|
33
|
-
|
|
70
|
+
ValidacaoError: Se prefixo ou data_extracao forem vazios.
|
|
71
|
+
DiretorioError: Se houver erro ao criar diretórios de log.
|
|
34
72
|
|
|
35
73
|
Examples:
|
|
36
|
-
|
|
37
|
-
|
|
74
|
+
Configuração básica:
|
|
75
|
+
|
|
76
|
+
>>> from nia_etl_utils import configurar_logger
|
|
77
|
+
>>> from loguru import logger
|
|
78
|
+
>>> caminho = configurar_logger("extract", "2025_01_19")
|
|
38
79
|
>>> logger.info("Pipeline iniciado")
|
|
39
80
|
>>> # Log salvo em: logs/extract/extract_2025_01_19.log
|
|
40
81
|
|
|
41
|
-
|
|
42
|
-
|
|
82
|
+
Com configurações customizadas:
|
|
83
|
+
|
|
84
|
+
>>> caminho = configurar_logger(
|
|
43
85
|
... prefixo="etl_ouvidorias",
|
|
44
86
|
... data_extracao="2025_01_19",
|
|
45
87
|
... pasta_logs="/var/logs/nia",
|
|
@@ -48,16 +90,20 @@ def configurar_logger(
|
|
|
48
90
|
... level="INFO"
|
|
49
91
|
... )
|
|
50
92
|
"""
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
93
|
+
# Validações
|
|
94
|
+
if not prefixo or not prefixo.strip():
|
|
95
|
+
raise ValidacaoError(
|
|
96
|
+
"Prefixo não pode ser vazio",
|
|
97
|
+
details={"parametro": "prefixo", "valor": prefixo}
|
|
98
|
+
)
|
|
56
99
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
100
|
+
if not data_extracao or not data_extracao.strip():
|
|
101
|
+
raise ValidacaoError(
|
|
102
|
+
"Data de extração não pode ser vazia",
|
|
103
|
+
details={"parametro": "data_extracao", "valor": data_extracao}
|
|
104
|
+
)
|
|
60
105
|
|
|
106
|
+
try:
|
|
61
107
|
# Cria estrutura de diretórios
|
|
62
108
|
diretorio_log = Path(pasta_logs) / prefixo
|
|
63
109
|
diretorio_log.mkdir(parents=True, exist_ok=True)
|
|
@@ -79,15 +125,16 @@ def configurar_logger(
|
|
|
79
125
|
|
|
80
126
|
return str(caminho_log)
|
|
81
127
|
|
|
82
|
-
except PermissionError as
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
128
|
+
except PermissionError as e:
|
|
129
|
+
raise DiretorioError(
|
|
130
|
+
f"Sem permissão para criar diretório de logs '{pasta_logs}'",
|
|
131
|
+
details={"pasta": pasta_logs, "erro": str(e)}
|
|
132
|
+
) from e
|
|
133
|
+
except OSError as e:
|
|
134
|
+
raise DiretorioError(
|
|
135
|
+
f"Erro do sistema ao configurar logger em '{pasta_logs}'",
|
|
136
|
+
details={"pasta": pasta_logs, "erro": str(e)}
|
|
137
|
+
) from e
|
|
91
138
|
|
|
92
139
|
|
|
93
140
|
def configurar_logger_padrao_nia(nome_pipeline: str) -> str:
|
|
@@ -104,17 +151,19 @@ def configurar_logger_padrao_nia(nome_pipeline: str) -> str:
|
|
|
104
151
|
nome_pipeline: Nome do pipeline (será usado como prefixo e na data).
|
|
105
152
|
|
|
106
153
|
Returns:
|
|
107
|
-
|
|
154
|
+
Caminho completo do arquivo de log criado.
|
|
155
|
+
|
|
156
|
+
Raises:
|
|
157
|
+
ValidacaoError: Se nome_pipeline for vazio.
|
|
158
|
+
DiretorioError: Se houver erro ao criar diretórios.
|
|
108
159
|
|
|
109
160
|
Examples:
|
|
110
|
-
>>> from nia_etl_utils
|
|
111
|
-
>>> from
|
|
161
|
+
>>> from nia_etl_utils import configurar_logger_padrao_nia
|
|
162
|
+
>>> from loguru import logger
|
|
112
163
|
>>>
|
|
113
|
-
>>>
|
|
164
|
+
>>> caminho = configurar_logger_padrao_nia("ouvidorias_etl")
|
|
114
165
|
>>> logger.info("Pipeline iniciado com configurações padrão NIA")
|
|
115
166
|
"""
|
|
116
|
-
from datetime import datetime
|
|
117
|
-
|
|
118
167
|
data_hoje = datetime.now().strftime("%Y_%m_%d")
|
|
119
168
|
|
|
120
169
|
return configurar_logger(
|
|
@@ -133,8 +182,12 @@ def remover_handlers_existentes() -> None:
|
|
|
133
182
|
Útil quando você precisa reconfigurar o logger do zero ou quando está
|
|
134
183
|
rodando múltiplos scripts em sequência que configuram o logger.
|
|
135
184
|
|
|
185
|
+
Note:
|
|
186
|
+
Após chamar esta função, apenas o handler padrão (stderr) estará
|
|
187
|
+
ativo. Chame configurar_logger() para adicionar novos handlers.
|
|
188
|
+
|
|
136
189
|
Examples:
|
|
137
|
-
>>> from nia_etl_utils
|
|
190
|
+
>>> from nia_etl_utils import remover_handlers_existentes, configurar_logger
|
|
138
191
|
>>>
|
|
139
192
|
>>> # Remove handlers anteriores
|
|
140
193
|
>>> remover_handlers_existentes()
|
|
@@ -143,4 +196,9 @@ def remover_handlers_existentes() -> None:
|
|
|
143
196
|
>>> configurar_logger("novo_pipeline", "2025_01_19")
|
|
144
197
|
"""
|
|
145
198
|
logger.remove()
|
|
146
|
-
logger.
|
|
199
|
+
logger.add(
|
|
200
|
+
sink=lambda msg: print(msg, end=""),
|
|
201
|
+
level="DEBUG",
|
|
202
|
+
format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {message}"
|
|
203
|
+
)
|
|
204
|
+
logger.debug("Handlers do logger foram resetados.")
|