impulsogov / etl Goto Github PK
View Code? Open in Web Editor NEWExtração, tratamento e caregamento de dados públicos direta ou indiretamente relacionados ao Sistema Único de Saúde brasileiro, tendo como destino o banco de dados da ImpulsoGov.
Extração, tratamento e caregamento de dados públicos direta ou indiretamente relacionados ao Sistema Único de Saúde brasileiro, tendo como destino o banco de dados da ImpulsoGov.
Erro ao capturar os arquivos de disseminação dos Registros de Ações Ambulatoriais em Saúde - Psicossociais (RAAS-PS) na competência de 20/2016 para o estado do Espírito Santo:
2022-09-04 09:29:36.091 | INFO | impulsoetl.scripts.saude_mental:raas_disseminacao:122 - Capturando RAAS Psicossociais do SIASUS.
2022-09-04 09:29:38.250 | INFO | impulsoetl.siasus.raas_ps:obter_raas_ps:364 - Iniciando captura de RAAS-Psicossociais para Unidade Federativa Federativa 'ES' na competencia de 10/2016.
2022-09-04 09:29:38.251 | INFO | impulsoetl.utilitarios.datasus_ftp:extrair_dbc_lotes:145 - Conectando-se ao servidor FTP `ftp.datasus.gov.br`...
2022-09-04 09:29:39.073 | INFO | impulsoetl.utilitarios.datasus_ftp:extrair_dbc_lotes:148 - Conexão estabelecida com sucesso!
2022-09-04 09:29:39.074 | INFO | impulsoetl.utilitarios.datasus_ftp:extrair_dbc_lotes:152 - Buscando diretório `/dissemin/publicos/SIASUS/200801_/Dados`...
2022-09-04 09:29:39.205 | INFO | impulsoetl.utilitarios.datasus_ftp:extrair_dbc_lotes:154 - OK!
2022-09-04 09:29:39.206 | INFO | impulsoetl.utilitarios.datasus_ftp:_listar_arquivos:82 - Listando arquivos compatíveis...
2022-09-04 09:29:40.722 | INFO | impulsoetl.utilitarios.datasus_ftp:_listar_arquivos:100 - Encontrados 1 arquivos.
2022-09-04 09:29:40.723 | INFO | impulsoetl.utilitarios.datasus_ftp:extrair_dbc_lotes:161 - Preparando ambiente para o download...
2022-09-04 09:29:40.724 | INFO | impulsoetl.utilitarios.datasus_ftp:extrair_dbc_lotes:167 - Tudo pronto para o download.
2022-09-04 09:29:40.725 | INFO | impulsoetl.utilitarios.datasus_ftp:extrair_dbc_lotes:177 - Iniciando download do arquivo `PSES1610.dbc`...
2022-09-04 09:29:42.578 | INFO | impulsoetl.utilitarios.datasus_ftp:extrair_dbc_lotes:184 - Download concluído.
2022-09-04 09:29:42.710 | INFO | impulsoetl.utilitarios.datasus_ftp:_checar_arquivo_corrompido:34 - Checando integridade do arquivo baixado...
2022-09-04 09:29:42.711 | DEBUG | impulsoetl.utilitarios.datasus_ftp:_checar_arquivo_corrompido:35 - Tamanho declarado do arquivo no FTP: 110000 bytes
2022-09-04 09:29:42.711 | DEBUG | impulsoetl.utilitarios.datasus_ftp:_checar_arquivo_corrompido:39 - Tamanho do arquivo baixado: 110000 bytes
2022-09-04 09:29:42.711 | INFO | impulsoetl.utilitarios.datasus_ftp:_checar_arquivo_corrompido:54 - OK!
2022-09-04 09:29:42.712 | INFO | impulsoetl.utilitarios.datasus_ftp:extrair_dbc_lotes:201 - Descompactando arquivo DBC...
2022-09-04 09:29:42.718 | INFO | impulsoetl.utilitarios.datasus_ftp:extrair_dbc_lotes:204 - Lendo arquivo DBF...
2022-09-04 09:29:42.720 | INFO | impulsoetl.utilitarios.datasus_ftp:extrair_dbc_lotes:214 - Lendo trecho do arquivo DBF disponibilizado pelo DataSUS e convertendo em DataFrame (linhas 0 a 400000)...
2022-09-04 09:29:43.136 | INFO | impulsoetl.siasus.raas_ps:transformar_raas_ps:231 - Transformando DataFrame com 4706 registros de RAAS.
2022-09-04 09:29:45.431 | ERROR | __main__:<module>:2 - An error has been caught in function '<module>', process 'MainProcess' (154171), thread 'MainThread' (139960620660544):
Traceback (most recent call last):
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/arrays/datetimes.py", line 2211, in objects_to_datetime64ns
values, tz_parsed = conversion.datetime_to_datetime64(data.ravel("K"))
│ │ │ └ <method 'ravel' of 'numpy.ndarray' objects>
│ │ └ array([nan, ' YY10DD'], dtype=object)
│ └ <built-in function datetime_to_datetime64>
└ <module 'pandas._libs.tslibs.conversion' from '/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/_libs/tslibs/conve...
File "pandas/_libs/tslibs/conversion.pyx", line 360, in pandas._libs.tslibs.conversion.datetime_to_datetime64
raise TypeError(f'Unrecognized value type: {type(val)}')
TypeError: Unrecognized value type: <class 'str'>
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
> File "<stdin>", line 2, in <module>
File "/home/bernardo/etl/src/impulsoetl/scripts/saude_mental.py", line 134, in raas_disseminacao
obter_raas_ps(
└ <function obter_raas_ps at 0x7f4b03fb4dc0>
File "/home/bernardo/etl/src/impulsoetl/siasus/raas_ps.py", line 382, in obter_raas_ps
raas_ps_transformada = transformar_raas_ps(
└ <function transformar_raas_ps at 0x7f4b03fb4d30>
File "/home/bernardo/etl/src/impulsoetl/siasus/raas_ps.py", line 245, in transformar_raas_ps
raas_ps # noqa: WPS221 # ignorar linha complexa no pipeline
└ CNES_EXEC GESTAO CONDIC UFMUN TPUPS TIPPRE MN_IND CNPJCPF ... TP_DROGA LOC_REALIZ INICIO FIM PERM...
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/generic.py", line 5898, in astype
res_col = col.astype(dtype=cdt, copy=copy, errors=errors)
│ │ │ │ └ 'raise'
│ │ │ └ True
│ │ └ 'datetime64[ns]'
│ └ <function NDFrame.astype at 0x7f4b10c39e50>
└ 0 NaN
1 NaN
2 NaN
3 NaN
4 NaN
...
4701 NaN
4702 NaN
4703 NaN
4704 NaN
4705 ...
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/generic.py", line 5912, in astype
new_data = self._mgr.astype(dtype=dtype, copy=copy, errors=errors)
│ │ │ │ │ └ 'raise'
│ │ │ │ └ True
│ │ │ └ 'datetime64[ns]'
│ │ └ <function BaseBlockManager.astype at 0x7f4b10d89940>
│ └ SingleBlockManager
│ Items: RangeIndex(start=0, stop=4706, step=1)
│ ObjectBlock: 4706 dtype: object
└ 0 NaN
1 NaN
2 NaN
3 NaN
4 NaN
...
4701 NaN
4702 NaN
4703 NaN
4704 NaN
4705 ...
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/internals/managers.py", line 419, in astype
return self.apply("astype", dtype=dtype, copy=copy, errors=errors)
│ │ │ │ └ 'raise'
│ │ │ └ True
│ │ └ 'datetime64[ns]'
│ └ <function BaseBlockManager.apply at 0x7f4b10d894c0>
└ SingleBlockManager
Items: RangeIndex(start=0, stop=4706, step=1)
ObjectBlock: 4706 dtype: object
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/internals/managers.py", line 304, in apply
applied = getattr(b, f)(**kwargs)
│ │ └ {'dtype': 'datetime64[ns]', 'copy': True, 'errors': 'raise'}
│ └ 'astype'
└ ObjectBlock: 4706 dtype: object
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/internals/blocks.py", line 580, in astype
new_values = astype_array_safe(values, dtype, copy=copy, errors=errors)
│ │ │ │ └ 'raise'
│ │ │ └ True
│ │ └ 'datetime64[ns]'
│ └ array([nan, nan, nan, ..., nan, nan, nan], dtype=object)
└ <function astype_array_safe at 0x7f4b11944700>
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/dtypes/cast.py", line 1292, in astype_array_safe
new_values = astype_array(values, dtype, copy=copy)
│ │ │ └ True
│ │ └ dtype('<M8[ns]')
│ └ array([nan, nan, nan, ..., nan, nan, nan], dtype=object)
└ <function astype_array at 0x7f4b11944670>
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/dtypes/cast.py", line 1237, in astype_array
values = astype_nansafe(values, dtype, copy=copy)
│ │ │ └ True
│ │ └ dtype('<M8[ns]')
│ └ array([nan, nan, nan, ..., nan, nan, nan], dtype=object)
└ <function astype_nansafe at 0x7f4b11944550>
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/dtypes/cast.py", line 1163, in astype_nansafe
to_datetime(arr).values,
│ └ array([nan, nan, nan, ..., nan, nan, nan], dtype=object)
└ <function to_datetime at 0x7f4b10bf3ee0>
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/tools/datetimes.py", line 1063, in to_datetime
cache_array = _maybe_cache(arg, format, cache, convert_listlike)
│ │ │ │ └ functools.partial(<function _convert_listlike_datetimes at 0x7f4b10bf3c10>, tz=None, unit=None, dayfirst=False, yearfirst=Fal...
│ │ │ └ True
│ │ └ None
│ └ array([nan, nan, nan, ..., nan, nan, nan], dtype=object)
└ <function _maybe_cache at 0x7f4b10bf39d0>
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/tools/datetimes.py", line 197, in _maybe_cache
cache_dates = convert_listlike(unique_dates, format)
│ │ └ None
│ └ array([nan, ' YY10DD'], dtype=object)
└ functools.partial(<function _convert_listlike_datetimes at 0x7f4b10bf3c10>, tz=None, unit=None, dayfirst=False, yearfirst=Fal...
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/tools/datetimes.py", line 402, in _convert_listlike_datetimes
result, tz_parsed = objects_to_datetime64ns(
└ <function objects_to_datetime64ns at 0x7f4b117145e0>
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/arrays/datetimes.py", line 2217, in objects_to_datetime64ns
raise err
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/arrays/datetimes.py", line 2199, in objects_to_datetime64ns
result, tz_parsed = tslib.array_to_datetime(
│ └ <built-in function array_to_datetime>
└ <module 'pandas._libs.tslib' from '/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/_libs/tslib.cpython-39-x86_64-...
File "pandas/_libs/tslib.pyx", line 381, in pandas._libs.tslib.array_to_datetime
cpdef array_to_datetime(
└ <built-in function array_to_datetime>
File "pandas/_libs/tslib.pyx", line 613, in pandas._libs.tslib.array_to_datetime
return _array_to_datetime_object(values, errors, dayfirst, yearfirst)
File "pandas/_libs/tslib.pyx", line 751, in pandas._libs.tslib._array_to_datetime_object
raise
File "pandas/_libs/tslib.pyx", line 742, in pandas._libs.tslib._array_to_datetime_object
oresult[i] = parse_datetime_string(val, dayfirst=dayfirst,
└ <built-in function parse_datetime_string>
File "pandas/_libs/tslibs/parsing.pyx", line 281, in pandas._libs.tslibs.parsing.parse_datetime_string
dt = du_parse(date_string, default=_DEFAULT_DATETIME,
│ └ datetime.datetime(1, 1, 1, 0, 0)
└ <function parse at 0x7f4b15a45b80>
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/dateutil/parser/_parser.py", line 1368, in parse
return DEFAULTPARSER.parse(timestr, **kwargs)
│ │ │ └ {'default': datetime.datetime(1, 1, 1, 0, 0), 'dayfirst': False, 'yearfirst': False}
│ │ └ ' YY10DD'
│ └ <function parser.parse at 0x7f4b158e1f70>
└ <dateutil.parser._parser.parser object at 0x7f4b158dc760>
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/dateutil/parser/_parser.py", line 643, in parse
raise ParserError("Unknown string format: %s", timestr)
│ └ ' YY10DD'
└ <class 'dateutil.parser._parser.ParserError'>
dateutil.parser._parser.ParserError: Unknown string format: YY10DD
2022-09-04 at 09:29:45 | ERROR | <stdin>:2: An error has been caught in function '<module>', process 'MainProcess' (154171), thread 'MainThread' (139960620660544):
Traceback (most recent call last):
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/arrays/datetimes.py", line 2211, in objects_to_datetime64ns
values, tz_parsed = conversion.datetime_to_datetime64(data.ravel("K"))
│ │ │ └ <method 'ravel' of 'numpy.ndarray' objects>
│ │ └ array([nan, ' YY10DD'], dtype=object)
│ └ <built-in function datetime_to_datetime64>
└ <module 'pandas._libs.tslibs.conversion' from '/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/_libs/tslibs/conve...
File "pandas/_libs/tslibs/conversion.pyx", line 360, in pandas._libs.tslibs.conversion.datetime_to_datetime64
raise TypeError(f'Unrecognized value type: {type(val)}')
TypeError: Unrecognized value type: <class 'str'>
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
> File "<stdin>", line 2, in <module>
File "/home/bernardo/etl/src/impulsoetl/scripts/saude_mental.py", line 134, in raas_disseminacao
obter_raas_ps(
└ <function obter_raas_ps at 0x7f4b03fb4dc0>
File "/home/bernardo/etl/src/impulsoetl/siasus/raas_ps.py", line 382, in obter_raas_ps
raas_ps_transformada = transformar_raas_ps(
└ <function transformar_raas_ps at 0x7f4b03fb4d30>
File "/home/bernardo/etl/src/impulsoetl/siasus/raas_ps.py", line 245, in transformar_raas_ps
raas_ps # noqa: WPS221 # ignorar linha complexa no pipeline
└ CNES_EXEC GESTAO CONDIC UFMUN TPUPS TIPPRE MN_IND CNPJCPF ... TP_DROGA LOC_REALIZ INICIO FIM PERM...
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/generic.py", line 5898, in astype
res_col = col.astype(dtype=cdt, copy=copy, errors=errors)
│ │ │ │ └ 'raise'
│ │ │ └ True
│ │ └ 'datetime64[ns]'
│ └ <function NDFrame.astype at 0x7f4b10c39e50>
└ 0 NaN
1 NaN
2 NaN
3 NaN
4 NaN
...
4701 NaN
4702 NaN
4703 NaN
4704 NaN
4705 ...
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/generic.py", line 5912, in astype
new_data = self._mgr.astype(dtype=dtype, copy=copy, errors=errors)
│ │ │ │ │ └ 'raise'
│ │ │ │ └ True
│ │ │ └ 'datetime64[ns]'
│ │ └ <function BaseBlockManager.astype at 0x7f4b10d89940>
│ └ SingleBlockManager
│ Items: RangeIndex(start=0, stop=4706, step=1)
│ ObjectBlock: 4706 dtype: object
└ 0 NaN
1 NaN
2 NaN
3 NaN
4 NaN
...
4701 NaN
4702 NaN
4703 NaN
4704 NaN
4705 ...
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/internals/managers.py", line 419, in astype
return self.apply("astype", dtype=dtype, copy=copy, errors=errors)
│ │ │ │ └ 'raise'
│ │ │ └ True
│ │ └ 'datetime64[ns]'
│ └ <function BaseBlockManager.apply at 0x7f4b10d894c0>
└ SingleBlockManager
Items: RangeIndex(start=0, stop=4706, step=1)
ObjectBlock: 4706 dtype: object
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/internals/managers.py", line 304, in apply
applied = getattr(b, f)(**kwargs)
│ │ └ {'dtype': 'datetime64[ns]', 'copy': True, 'errors': 'raise'}
│ └ 'astype'
└ ObjectBlock: 4706 dtype: object
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/internals/blocks.py", line 580, in astype
new_values = astype_array_safe(values, dtype, copy=copy, errors=errors)
│ │ │ │ └ 'raise'
│ │ │ └ True
│ │ └ 'datetime64[ns]'
│ └ array([nan, nan, nan, ..., nan, nan, nan], dtype=object)
└ <function astype_array_safe at 0x7f4b11944700>
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/dtypes/cast.py", line 1292, in astype_array_safe
new_values = astype_array(values, dtype, copy=copy)
│ │ │ └ True
│ │ └ dtype('<M8[ns]')
│ └ array([nan, nan, nan, ..., nan, nan, nan], dtype=object)
└ <function astype_array at 0x7f4b11944670>
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/dtypes/cast.py", line 1237, in astype_array
values = astype_nansafe(values, dtype, copy=copy)
│ │ │ └ True
│ │ └ dtype('<M8[ns]')
│ └ array([nan, nan, nan, ..., nan, nan, nan], dtype=object)
└ <function astype_nansafe at 0x7f4b11944550>
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/dtypes/cast.py", line 1163, in astype_nansafe
to_datetime(arr).values,
│ └ array([nan, nan, nan, ..., nan, nan, nan], dtype=object)
└ <function to_datetime at 0x7f4b10bf3ee0>
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/tools/datetimes.py", line 1063, in to_datetime
cache_array = _maybe_cache(arg, format, cache, convert_listlike)
│ │ │ │ └ functools.partial(<function _convert_listlike_datetimes at 0x7f4b10bf3c10>, tz=None, unit=None, dayfirst=False, yearfirst=Fal...
│ │ │ └ True
│ │ └ None
│ └ array([nan, nan, nan, ..., nan, nan, nan], dtype=object)
└ <function _maybe_cache at 0x7f4b10bf39d0>
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/tools/datetimes.py", line 197, in _maybe_cache
cache_dates = convert_listlike(unique_dates, format)
│ │ └ None
│ └ array([nan, ' YY10DD'], dtype=object)
└ functools.partial(<function _convert_listlike_datetimes at 0x7f4b10bf3c10>, tz=None, unit=None, dayfirst=False, yearfirst=Fal...
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/tools/datetimes.py", line 402, in _convert_listlike_datetimes
result, tz_parsed = objects_to_datetime64ns(
└ <function objects_to_datetime64ns at 0x7f4b117145e0>
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/arrays/datetimes.py", line 2217, in objects_to_datetime64ns
raise err
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/core/arrays/datetimes.py", line 2199, in objects_to_datetime64ns
result, tz_parsed = tslib.array_to_datetime(
│ └ <built-in function array_to_datetime>
└ <module 'pandas._libs.tslib' from '/home/bernardo/etl/.venv/lib/python3.9/site-packages/pandas/_libs/tslib.cpython-39-x86_64-...
File "pandas/_libs/tslib.pyx", line 381, in pandas._libs.tslib.array_to_datetime
cpdef array_to_datetime(
└ <built-in function array_to_datetime>
File "pandas/_libs/tslib.pyx", line 613, in pandas._libs.tslib.array_to_datetime
return _array_to_datetime_object(values, errors, dayfirst, yearfirst)
File "pandas/_libs/tslib.pyx", line 751, in pandas._libs.tslib._array_to_datetime_object
raise
File "pandas/_libs/tslib.pyx", line 742, in pandas._libs.tslib._array_to_datetime_object
oresult[i] = parse_datetime_string(val, dayfirst=dayfirst,
└ <built-in function parse_datetime_string>
File "pandas/_libs/tslibs/parsing.pyx", line 281, in pandas._libs.tslibs.parsing.parse_datetime_string
dt = du_parse(date_string, default=_DEFAULT_DATETIME,
│ └ datetime.datetime(1, 1, 1, 0, 0)
└ <function parse at 0x7f4b15a45b80>
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/dateutil/parser/_parser.py", line 1368, in parse
return DEFAULTPARSER.parse(timestr, **kwargs)
│ │ │ └ {'default': datetime.datetime(1, 1, 1, 0, 0), 'dayfirst': False, 'yearfirst': False}
│ │ └ ' YY10DD'
│ └ <function parser.parse at 0x7f4b158e1f70>
└ <dateutil.parser._parser.parser object at 0x7f4b158dc760>
File "/home/bernardo/etl/.venv/lib/python3.9/site-packages/dateutil/parser/_parser.py", line 643, in parse
raise ParserError("Unknown string format: %s", timestr)
│ └ ' YY10DD'
└ <class 'dateutil.parser._parser.ParserError'>
dateutil.parser._parser.ParserError: Unknown string format: YY10DD
Adicionar argumento condicoes
nas funções de ETL obter_*
e transformar_*
para filtrar os dados baixados de fontes externas, limitando a ingestão a apenas uma parte dos registros. Os valores deste argumento seriam informados por meio do campo parametros
da view configuracoes.capturas_agendamentos
disponível no banco de dados.
Essa funcionalidade está pensada para ser uma solução temporária que limite problemas de performance derivados da obtenção de grandes bases de dados do SIASUS. Com essa funcionalidade, apenas os dados essenciais para algum projeto ou produto da Impulso poderão ser carregados para o banco, limitando o tamanho das tabelas armazenadas e acessadas.
Remover o grupo de ETLs legados localizados no subpacote src/impulsoprevine
, já que não são mais utilizados. Inclui também ajustar o README.md e os fluxos do GitHub Actions de acordo.
Mortalidade é uma das possíveis variáveis a serem utilizadas para definir a relevância de outros indicadores no processo de validação estatística dos indicadores de saúde mental.
Esses dados são divulgados anualmente no FTP do Datasus e no [Opendatasus](https://opendatasus.saude.gov.br/dataset?q=SIM). Porém, eles ainda não foram incorporados ao banco de dados da Impulso.
Esta tarefa consiste em providenciar a ingestão automatizada dos dados do SIM para o banco de dados da Impulso.
Adicionar os microdados dos arquivos de disseminação do Sistema de Informação de Agravos de Notificação (SINAN) relativos aos agravos de violência pessoal/autoprovocada.
Esses dados são relevantes para o acompanhamento dos casos de conduta autolesiva no âmbito do projeto de Saúde Mental.
O painel de saúde mental consome dados dos relatórios de produção do SISAB para disponibilizar informações como o número de atendimentos individuais das equipes de consultório na rua e a quantidade de atendimentos e encaminhamentos em saúde mental da Atenção Primária à Saúde.
Atualmente, a extração desses dados usa a biblioteca Selenium, que basicamente cria um navegador de internet e automatiza todos os movimentos que um humano faria nele - no nosso caso, por exemplo, clica em todos os elementos da interface necessários para configurar e baixar um relatório na página do SISAB.
Essa forma de extrair dados de uma página web é lenta e bastante propensa a erros (por exemplo, se houver qualquer mudança na interface), além de, em geral, gerar códigos mais complexos e difíceis de manter. Depois que implementamos essa forma de extração para os primeiros relatórios do SISAB, o @dlopes14 conseguiu resolver o problema de uma forma muito mais eficiente: imitando as requisições HTTP que o navegador faz quando pedimos um relatório com certas configurações, sem precisar definir essas configurações pela interface.
Essa nova forma de extrair dados no SISAB utiliza a biblioteca requests e já está implementada em diversos ETLs do Impulso Previne (exemplo), mas ainda não nos ETLs de relatórios de produção utilizados pelo projuto de Saúde Mental.
Esta tarefa consiste em alterar o arquivo [src/impulsoetl/sisab/producao.py](https://github.com/ImpulsoGov/etl/blob/main/src/impulsoetl/sisab/producao.py)
para que a extração passe a ser realizada por meio de requisições HTTP que simulam a consulta realizada no navegador - e não mais utilizando o Selenium.
O arquivo está estruturado com uma lógica bem diferente de como fazemos os ETLs hoje; não necessariamente vamos chegar até o ponto de corrigir o ETL completo, mas queremos ter pelo menos uma função extrair_relatorio_producao()
que funcione no mínimo com os conjuntos de parâmetros já usados hoje para obter os relatórios de tipos de atendimento por tipos de equipe e de condutas/desfechos por problema/condição avaliada. Podem ser necessárias alterações também na função obter_relatorio_producao()
mas, na medida do possível, gostaríamos de evitar grandes mudanças na interface dessa função (isto é, quais parâmetros ela recebe, quais são os tipos desses parâmetros…).
Atualmente, utilizamos os logs do GitHub Actions para acompanhar eventuais erros que aconteçam no processo de captura.
Para maior transparência e monitoramento desses erros, seria interessante registrá-los em uma tabela específica no banco de dados, com informações como:
Ao processar dados do relatório de produção do SISAB, é levantado um erro ValueError
com a mensagem 'badly formed hexadecimal UUID string'
:
# ...
value = _python_UUID(value)
│ └ 'listas_de_codigos.unidades_geograficas'
└ <class 'uuid.UUID'>
File "/usr/local/lib/python3.8/uuid.py", line 171, in __init__
raise ValueError('badly formed hexadecimal UUID string')
# ...
2022-09-25 04:35:25.619 | INFO | impulso***.sisab.producao:obter_relatorio_producao:1346 - Iniciando captura de relatório de produção com as variáveis ['Tipo de Equipe', 'Tipo de Produção'] para 1 municípios na competencia de 7/2022.
2022-09-25 04:35:28.703 | ERROR | impulso***.scripts.saude_mental:***:319 - An error has been caught in function '***', process 'MainProcess' (1), thread 'MainThread' (139913496258368):
Traceback (most recent call last):
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1702, in _execute_context
context = constructor(
└ <bound method DefaultExecutionContext._init_compiled of <class 'sqlalchemy.dialects.postgresql.psycopg2.PGExecutionContext_ps...
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 1078, in _init_compiled
param = {
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 1079, in <dictcomp>
key: processors[key](compiled_params[key])
│ │ │ │ └ 'id_1'
│ │ │ └ {'id_1': 'listas_de_codigos.unidades_geograficas'}
│ │ └ 'id_1'
│ └ {'id_1': <function _PGUUID.bind_processor.<locals>.process at 0x7f3ffe521820>}
└ 'id_1'
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/dialects/postgresql/psycopg2.py", line 581, in process
value = _python_UUID(value)
│ └ 'listas_de_codigos.unidades_geograficas'
└ <class 'uuid.UUID'>
File "/usr/local/lib/python3.8/uuid.py", line 171, in __init__
raise ValueError('badly formed hexadecimal UUID string')
ValueError: badly formed hexadecimal UUID string
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/local/lib/python3.8/runpy.py", line 194, in _run_module_as_main
return _run_code(code, main_globals, None,
│ │ └ {'__name__': '__main__', '__doc__': 'Executa todos os scripts de ETL.', '__package__': 'impulso***', '__loader__': <_frozen_i...
│ └ <code object <module> at 0x7f402628a0e0, file "/home/appuser/src/impulso***/__main__.py", line 8>
└ <function _run_code at 0x7f402627ff70>
File "/usr/local/lib/python3.8/runpy.py", line 87, in _run_code
exec(code, run_globals)
│ └ {'__name__': '__main__', '__doc__': 'Executa todos os scripts de ETL.', '__package__': 'impulso***', '__loader__': <_frozen_i...
└ <code object <module> at 0x7f402628a0e0, file "/home/appuser/src/impulso***/__main__.py", line 8>
File "/home/appuser/src/impulso***/__main__.py", line 14, in <module>
***()
└ <function *** at 0x7f4026133550>
File "/home/appuser/src/impulso***/***.py", line 18, in ***
capturas_saude_mental(sessao=sessao, teste=teste)
│ │ └ False
│ └ <sqlalchemy.orm.session.Session object at 0x7f4026283040>
└ <function *** at 0x7f4009f8d0d0>
> File "/home/appuser/src/impulso***/scripts/saude_mental.py", line 319, in ***
tipo_equipe_por_tipo_producao(sessao=sessao, teste=teste)
│ │ └ False
│ └ <sqlalchemy.orm.session.Session object at 0x7f4026283040>
└ <function tipo_equipe_por_tipo_producao at 0x7f4009f85040>
File "/home/appuser/src/impulso***/scripts/saude_mental.py", line 101, in tipo_equipe_por_tipo_producao
obter_relatorio_producao(
└ <function obter_relatorio_producao at 0x7f4009f89ca0>
File "/home/appuser/src/impulso***/utilitarios/repetidores.py", line 178, in wrapper
[
File "/home/appuser/src/impulso***/utilitarios/repetidores.py", line 179, in <listcomp>
funcao(ano=dt.year, mes=dt.month, *args, **kwargs)
│ │ │ │ │ │ └ {'sessao': <sqlalchemy.orm.session.Session object at 0x7f4026283040>, 'tabela_destino': 'dados_publicos.sisab_producao_munici...
│ │ │ │ │ └ ()
│ │ │ │ └ <attribute 'month' of 'datetime.date' objects>
│ │ │ └ Timestamp('2022-07-01 00:00:00', freq='MS')
│ │ └ <attribute 'year' of 'datetime.date' objects>
│ └ Timestamp('2022-07-01 00:00:00', freq='MS')
└ <function obter_relatorio_producao at 0x7f4009f89c10>
File "/home/appuser/src/impulso***/sisab/producao.py", line 1370, in obter_relatorio_producao
unidade_geografica_id_sus = id_impulso_para_id_sus(
└ <functools._lru_cache_wrapper object at 0x7f400a91c160>
File "/home/appuser/src/impulso***/comum/geografias.py", line 141, in id_impulso_para_id_sus
sessao.query(unidades_geograficas.c.id_sus)
│ │ │ └ <property object at 0x7f401eb67[720](https://github.com/ImpulsoGov/etl/actions/runs/3120863573/jobs/5061772960#step:5:721)>
│ │ └ Table('unidades_geograficas', MetaData(bind=Engine(***:***/***)), Column('id'...
│ └ <function Session.query at 0x7f401f262820>
└ <sqlalchemy.orm.session.Session object at 0x7f4026283040>
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/orm/query.py", line 2856, in one
return self._iter().one()
│ └ <function Query._iter at 0x7f401ce301f0>
└ <sqlalchemy.orm.query.Query object at 0x7f3ffe544bb0>
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/orm/query.py", line 2894, in _iter
result = self.session.execute(
│ │ └ <function Session.execute at 0x7f401f2621f0>
│ └ <sqlalchemy.orm.session.Session object at 0x7f4026283040>
└ <sqlalchemy.orm.query.Query object at 0x7f3ffe544bb0>
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/orm/session.py", line 1689, in execute
result = conn._execute_20(statement, params or {}, execution_options)
│ │ │ │ └ immutabledict({'_sa_orm_load_options': default_load_options(_legacy_uniquing=True), '_result_disable_adapt_to_context': True,...
│ │ │ └ immutabledict({})
│ │ └ <sqlalchemy.sql.selectable.Select object at 0x7f3ffe5444c0>
│ └ <function Connection._execute_20 at 0x7f401eac7820>
└ <sqlalchemy.engine.base.Connection object at 0x7f4009e6e370>
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1614, in _execute_20
return meth(self, args_10style, kwargs_10style, execution_options)
│ │ │ │ └ immutabledict({'_sa_orm_load_options': default_load_options(_legacy_uniquing=True), '_result_disable_adapt_to_context': True,...
│ │ │ └ immutabledict({})
│ │ └ ({},)
│ └ <sqlalchemy.engine.base.Connection object at 0x7f4009e6e370>
└ <bound method ClauseElement._execute_on_connection of <sqlalchemy.sql.selectable.Select object at 0x7f3ffe5444c0>>
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/sql/elements.py", line 325, in _execute_on_connection
return connection._execute_clauseelement(
│ └ <function Connection._execute_clauseelement at 0x7f401eac7670>
└ <sqlalchemy.engine.base.Connection object at 0x7f4009e6e370>
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1481, in _execute_clauseelement
ret = self._execute_context(
│ └ <function Connection._execute_context at 0x7f401eac7940>
└ <sqlalchemy.engine.base.Connection object at 0x7f4009e6e370>
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1708, in _execute_context
self._handle_dbapi_exception(
│ └ <function Connection._handle_dbapi_exception at 0x7f401eac7af0>
└ <sqlalchemy.engine.base.Connection object at 0x7f4009e6e370>
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 2026, in _handle_dbapi_exception
util.raise_(
│ └ <function raise_ at 0x7f401f6ae9d0>
└ <module 'sqlalchemy.util' from '/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packag...
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/util/compat.py", line 207, in raise_
raise exception
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1702, in _execute_context
context = constructor(
└ <bound method DefaultExecutionContext._init_compiled of <class 'sqlalchemy.dialects.postgresql.psycopg2.PGExecutionContext_ps...
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 1078, in _init_compiled
param = {
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 1079, in <dictcomp>
key: processors[key](compiled_params[key])
│ │ │ │ └ 'id_1'
│ │ │ └ {'id_1': 'listas_de_codigos.unidades_geograficas'}
│ │ └ 'id_1'
│ └ {'id_1': <function _PGUUID.bind_processor.<locals>.process at 0x7f3ffe521820>}
└ 'id_1'
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/dialects/postgresql/psycopg2.py", line 581, in process
value = _python_UUID(value)
│ └ 'listas_de_codigos.unidades_geograficas'
└ <class 'uuid.UUID'>
File "/usr/local/lib/python3.8/uuid.py", line 171, in __init__
raise ValueError('badly formed hexadecimal UUID string')
sqlalchemy.exc.StatementError: (builtins.ValueError) badly formed hexadecimal UUID string
[SQL: SELECT listas_de_codigos.unidades_geograficas.id_sus AS listas_de_codigos_unidades_geograficas_id_sus
FROM listas_de_codigos.unidades_geograficas
WHERE listas_de_codigos.unidades_geograficas.id = %(id_1)s]
[parameters: [{}]]
2022-09-25 at 04:35:28 | ERROR | saude_mental.py:319: An error has been caught in function '***', process 'MainProcess' (1), thread 'MainThread' (139913496258368):
Traceback (most recent call last):
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1702, in _execute_context
context = constructor(
└ <bound method DefaultExecutionContext._init_compiled of <class 'sqlalchemy.dialects.postgresql.psycopg2.PGExecutionContext_ps...
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 1078, in _init_compiled
param = {
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 1079, in <dictcomp>
key: processors[key](compiled_params[key])
│ │ │ │ └ 'id_1'
│ │ │ └ {'id_1': 'listas_de_codigos.unidades_geograficas'}
│ │ └ 'id_1'
│ └ {'id_1': <function _PGUUID.bind_processor.<locals>.process at 0x7f3ffe521820>}
└ 'id_1'
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/dialects/postgresql/psycopg2.py", line 581, in process
value = _python_UUID(value)
│ └ 'listas_de_codigos.unidades_geograficas'
└ <class 'uuid.UUID'>
File "/usr/local/lib/python3.8/uuid.py", line 171, in __init__
raise ValueError('badly formed hexadecimal UUID string')
ValueError: badly formed hexadecimal UUID string
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/local/lib/python3.8/runpy.py", line 194, in _run_module_as_main
return _run_code(code, main_globals, None,
│ │ └ {'__name__': '__main__', '__doc__': 'Executa todos os scripts de ETL.', '__package__': 'impulso***', '__loader__': <_frozen_i...
│ └ <code object <module> at 0x7f402628a0e0, file "/home/appuser/src/impulso***/__main__.py", line 8>
└ <function _run_code at 0x7f402627ff70>
File "/usr/local/lib/python3.8/runpy.py", line 87, in _run_code
exec(code, run_globals)
│ └ {'__name__': '__main__', '__doc__': 'Executa todos os scripts de ETL.', '__package__': 'impulso***', '__loader__': <_frozen_i...
└ <code object <module> at 0x7f402628a0e0, file "/home/appuser/src/impulso***/__main__.py", line 8>
File "/home/appuser/src/impulso***/__main__.py", line 14, in <module>
***()
└ <function *** at 0x7f4026133550>
File "/home/appuser/src/impulso***/***.py", line 18, in ***
capturas_saude_mental(sessao=sessao, teste=teste)
│ │ └ False
│ └ <sqlalchemy.orm.session.Session object at 0x7f4026283040>
└ <function *** at 0x7f4009f8d0d0>
> File "/home/appuser/src/impulso***/scripts/saude_mental.py", line 319, in ***
tipo_equipe_por_tipo_producao(sessao=sessao, teste=teste)
│ │ └ False
│ └ <sqlalchemy.orm.session.Session object at 0x7f4026283040>
└ <function tipo_equipe_por_tipo_producao at 0x7f4009f85040>
File "/home/appuser/src/impulso***/scripts/saude_mental.py", line 101, in tipo_equipe_por_tipo_producao
obter_relatorio_producao(
└ <function obter_relatorio_producao at 0x7f4009f89ca0>
File "/home/appuser/src/impulso***/utilitarios/repetidores.py", line 178, in wrapper
[
File "/home/appuser/src/impulso***/utilitarios/repetidores.py", line 179, in <listcomp>
funcao(ano=dt.year, mes=dt.month, *args, **kwargs)
│ │ │ │ │ │ └ {'sessao': <sqlalchemy.orm.session.Session object at 0x7f4026283040>, 'tabela_destino': 'dados_publicos.sisab_producao_munici...
│ │ │ │ │ └ ()
│ │ │ │ └ <attribute 'month' of 'datetime.date' objects>
│ │ │ └ Timestamp('2022-07-01 00:00:00', freq='MS')
│ │ └ <attribute 'year' of 'datetime.date' objects>
│ └ Timestamp('2022-07-01 00:00:00', freq='MS')
└ <function obter_relatorio_producao at 0x7f4009f89c10>
File "/home/appuser/src/impulso***/sisab/producao.py", line 1370, in obter_relatorio_producao
unidade_geografica_id_sus = id_impulso_para_id_sus(
└ <functools._lru_cache_wrapper object at 0x7f400a91c160>
File "/home/appuser/src/impulso***/comum/geografias.py", line 141, in id_impulso_para_id_sus
sessao.query(unidades_geograficas.c.id_sus)
│ │ │ └ <property object at 0x7f401eb67720>
│ │ └ Table('unidades_geograficas', MetaData(bind=Engine(***:***/***)), Column('id'...
│ └ <function Session.query at 0x7f401f262820>
└ <sqlalchemy.orm.session.Session object at 0x7f4026283040>
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/orm/query.py", line 2856, in one
return self._iter().one()
│ └ <function Query._iter at 0x7f401ce301f0>
└ <sqlalchemy.orm.query.Query object at 0x7f3ffe544bb0>
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/orm/query.py", line 2894, in _iter
result = self.session.execute(
│ │ └ <function Session.execute at 0x7f401f2621f0>
│ └ <sqlalchemy.orm.session.Session object at 0x7f4026283040>
└ <sqlalchemy.orm.query.Query object at 0x7f3ffe544bb0>
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/orm/session.py", line 1689, in execute
result = conn._execute_20(statement, params or {}, execution_options)
│ │ │ │ └ immutabledict({'_sa_orm_load_options': default_load_options(_legacy_uniquing=True), '_result_disable_adapt_to_context': True,...
│ │ │ └ immutabledict({})
│ │ └ <sqlalchemy.sql.selectable.Select object at 0x7f3ffe5444c0>
│ └ <function Connection._execute_20 at 0x7f401eac7820>
└ <sqlalchemy.engine.base.Connection object at 0x7f4009e6e370>
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1614, in _execute_20
return meth(self, args_10style, kwargs_10style, execution_options)
│ │ │ │ └ immutabledict({'_sa_orm_load_options': default_load_options(_legacy_uniquing=True), '_result_disable_adapt_to_context': True,...
│ │ │ └ immutabledict({})
│ │ └ ({},)
│ └ <sqlalchemy.engine.base.Connection object at 0x7f4009e6e370>
└ <bound method ClauseElement._execute_on_connection of <sqlalchemy.sql.selectable.Select object at 0x7f3ffe5444c0>>
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/sql/elements.py", line 325, in _execute_on_connection
return connection._execute_clauseelement(
│ └ <function Connection._execute_clauseelement at 0x7f401eac[767](https://github.com/ImpulsoGov/etl/actions/runs/3120863573/jobs/5061772960#step:5:768)0>
└ <sqlalchemy.engine.base.Connection object at 0x7f4009e6e370>
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1481, in _execute_clauseelement
ret = self._execute_context(
│ └ <function Connection._execute_context at 0x7f401eac[794](https://github.com/ImpulsoGov/etl/actions/runs/3120863573/jobs/5061772960#step:5:795)0>
└ <sqlalchemy.engine.base.Connection object at 0x7f4009e6e370>
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1708, in _execute_context
self._handle_dbapi_exception(
│ └ <function Connection._handle_dbapi_exception at 0x7f401eac7af0>
└ <sqlalchemy.engine.base.Connection object at 0x7f4009e6e370>
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 2026, in _handle_dbapi_exception
util.raise_(
│ └ <function raise_ at 0x7f401f6ae9d0>
└ <module 'sqlalchemy.util' from '/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packag...
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/util/compat.py", line 207, in raise_
raise exception
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1702, in _execute_context
context = constructor(
└ <bound method DefaultExecutionContext._init_compiled of <class 'sqlalchemy.dialects.postgresql.psycopg2.PGExecutionContext_ps...
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 1078, in _init_compiled
param = {
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 1079, in <dictcomp>
key: processors[key](compiled_params[key])
│ │ │ │ └ 'id_1'
│ │ │ └ {'id_1': 'listas_de_codigos.unidades_geograficas'}
│ │ └ 'id_1'
│ └ {'id_1': <function _PGUUID.bind_processor.<locals>.process at 0x7f3ffe521[820](https://github.com/ImpulsoGov/etl/actions/runs/3120863573/jobs/5061772960#step:5:821)>}
└ 'id_1'
File "/home/appuser/.cache/pypoetry/virtualenvs/impulso***-nhdmnNHN-py3.8/lib/python3.8/site-packages/sqlalchemy/dialects/postgresql/psycopg2.py", line 581, in process
value = _python_UUID(value)
│ └ 'listas_de_codigos.unidades_geograficas'
└ <class 'uuid.UUID'>
File "/usr/local/lib/python3.8/uuid.py", line 171, in __init__
raise ValueError('badly formed hexadecimal UUID string')
sqlalchemy.exc.StatementError: (builtins.ValueError) badly formed hexadecimal UUID string
[SQL: SELECT listas_de_codigos.unidades_geograficas.id_sus AS listas_de_codigos_unidades_geograficas_id_sus
FROM listas_de_codigos.unidades_geograficas
WHERE listas_de_codigos.unidades_geograficas.id = %(id_1)s]
[parameters: [{}]]
Atualmente, boa parte das extrações de dados do FTP público do DataSUS (ftp.datasus.gov.br
) falha com uma mensagem semelhante a esta:
2022-08-15 06:04:19.769 | ERROR | impulso***.utilitarios.datasus_ftp:_checar_arquivo_corrompido:40 - Tamanho no servidor é maior do que o do arquivo baixado.
2022-08-15 at 06:04:19 | ERROR | datasus_ftp.py:40: Tamanho no servidor é maior do que o do arquivo baixado.
2022-08-15 06:04:19.771 | ERROR | impulso***.scripts.geral:***:95 - An error has been caught in function '***', process 'MainProcess' (1), thread 'MainThread' (139749888595776):
Traceback (most recent call last):
File "src/impulso***/__main__.py", line 14, in <module>
***()
└ <function *** at 0x7f1a0e483c10>
File "/home/appuser/.local/lib/python3.8/site-packages/impulso***/***.py", line 17, in ***
capturas_uso_geral(sessao=sessao, teste=teste)
│ │ └ False
│ └ <sqlalchemy.orm.session.Session object at 0x7f1a0e5089a0>
└ <function *** at 0x7f19eb4840d0>
> File "/home/appuser/.local/lib/python3.8/site-packages/impulso***/scripts/geral.py", line 95, in ***
vinculos_disseminacao(sessao=sessao, teste=teste)
│ │ └ False
│ └ <sqlalchemy.orm.session.Session object at 0x7f1a0e5089a0>
└ <function vinculos_disseminacao at 0x7f19eb533a60>
File "/home/appuser/.local/lib/python3.8/site-packages/impulso***/scripts/geral.py", line 37, in vinculos_disseminacao
obter_vinculos(
└ <function obter_vinculos at 0x7f19eb533700>
File "/home/appuser/.local/lib/python3.8/site-packages/impulso***/cnes/vinculos.py", line 382, in obter_vinculos
for vinculos_lote in vinculos_lotes:
└ <generator object extrair_dbc_lotes at 0x7f19ead95a50>
File "/home/appuser/.local/lib/python3.8/site-packages/impulso***/utilitarios/datasus_ftp.py", line [114](https://github.com/ImpulsoGov/etl/runs/7832903075?check_suite_focus=true#step:5:115), in extrair_dbc_lotes
raise RuntimeError(
RuntimeError: A extração da fonte `ftp.datasus.gov.br/dissemin/publicos/CNES/200508_/Dados/PF` falhou porque o arquivo baixado está corrompido.
Este comportamento é o esperado, e é motivado pelo fato de a função impulsoetl.utilitarios.datasus_ftp._checar_arquivo_corrompido()
detectar que o arquivo baixado tem alguns bytes a menos do que o tamanho informado pelo servidor FTP. Para evitar enviar dados corrompidos para o banco de dados, um erro RuntimeError
é levantado e a captura é interrompido.
Esta issue consiste em tentar alterar a função impulsoetl.utilitarios.datasus_ftp.extrair_dbc_lotes()
de forma que este erro seja menos recorrente.
A partir de janeiro de 2013, os arquivos de disseminação de procedimentos ambulatoriais do SIASUS para o estado de São Paulo passaram a ser divididos em várias partes, indicadas por letras ao final:
Como referência, as funções de download do PySUS também lidam com esse problema; ver issue AlertaDengue/PySUS#27 e a função pysus.online_data.SIA.check_file_split()
.
As capturas de relatórios do SISAB que ainda utilizam Selenium estão retornando um erro, aparentemente relacionado à permissão de acesso ao executável do navegador automatizado.
Logs do Github Action:
2022-07-19 06:05:30.453 | INFO | impulso***.scripts.saude_mental:resolutividade_aps_por_condicao:44 - Capturando dados de resolutividade da APS (desfechos de atendimentos individuais) por condição de saúde avaliada.
2022-07-19 06:05:30.716 | INFO | impulso***.sisab.producao:obter_relatorio_producao:1349 - Iniciando captura de relatório de produção com as variáveis ['Conduta', 'Problema/Condição Avaliada'] para 1 municípios na competencia de 5/2022.
2022-07-19 06:05:31.752 | ERROR | impulso***.scripts.saude_mental:***:304 - An error has been caught in function '***', process 'MainProcess' (1), thread 'MainThread' (140712654780224):
Traceback (most recent call last):
File "/home/appuser/.local/lib/python3.8/site-packages/selenium/webdriver/common/service.py", line 71, in start
self.process = subprocess.Popen(cmd, env=self.env,
│ │ │ │ │ └ environ({'PATH': '/home/appuser/.local/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', 'HOS...
│ │ │ │ └ <selenium.webdriver.firefox.service.Service object at 0x7ffa14303430>
│ │ │ └ ['', '--websocket-port', '38983', '--port', '55761']
│ │ └ <class 'subprocess.Popen'>
│ └ <module 'subprocess' from '/usr/local/lib/python3.8/subprocess.py'>
└ <selenium.webdriver.firefox.service.Service object at 0x7ffa14303430>
File "/usr/local/lib/python3.8/subprocess.py", line 858, in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
│ │ │ │ │ └ True
│ │ │ │ └ None
│ │ │ └ None
│ │ └ ['', '--websocket-port', '38983', '--port', '55761']
│ └ <function Popen._execute_child at 0x7ffa313c1280>
└ <subprocess.Popen object at 0x7ffa1424d880>
File "/usr/local/lib/python3.8/subprocess.py", line 1704, in _execute_child
raise child_exception_type(errno_num, err_msg, err_filename)
│ │ │ └ ''
│ │ └ 'Permission denied'
│ └ 13
└ <class 'OSError'>
PermissionError: [Errno 13] Permission denied: ''
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "src/impulso***/__main__.py", line 14, in <module>
***()
└ <function *** at 0x7ffa379e7c10>
File "/home/appuser/.local/lib/python3.8/site-packages/impulso***/***.py", line 18, in ***
capturas_saude_mental(sessao=sessao, teste=teste)
│ │ └ False
│ └ <sqlalchemy.orm.session.Session object at 0x7ffa37a6a9a0>
└ <function *** at 0x7ffa14302b80>
> File "/home/appuser/.local/lib/python3.8/site-packages/impulso***/scripts/saude_mental.py", line 304, in ***
resolutividade_aps_por_condicao(sessao=sessao, teste=teste)
│ │ └ False
│ └ <sqlalchemy.orm.session.Session object at 0x7ffa37a6a9a0>
└ <function resolutividade_aps_por_condicao at 0x7ffa14301670>
File "/home/appuser/.local/lib/python3.8/site-packages/impulso***/scripts/saude_mental.py", line 57, in resolutividade_aps_por_condicao
obter_relatorio_producao(
└ <function obter_relatorio_producao at 0x7ffa14301790>
File "/home/appuser/.local/lib/python3.8/site-packages/impulso***/utilitarios/repetidores.py", line 178, in wrapper
[
File "/home/appuser/.local/lib/python3.8/site-packages/impulso***/utilitarios/repetidores.py", line 179, in <listcomp>
funcao(ano=dt.year, mes=dt.month, *args, **kwargs)
│ │ │ │ │ │ └ {'tabela_destino': 'dados_publicos.sisab_producao_municipios_por_conduta_por_problema_condicao_ava', 'variaveis': ('Conduta',...
│ │ │ │ │ └ ()
│ │ │ │ └ <attribute 'month' of 'datetime.date' objects>
│ │ │ └ Timestamp('2022-05-01 00:00:00', freq='MS')
│ │ └ <attribute 'year' of 'datetime.date' objects>
│ └ Timestamp('2022-05-01 00:00:00', freq='MS')
└ <function obter_relatorio_producao at 0x7ffa14301700>
File "/home/appuser/.local/lib/python3.8/site-packages/impulso***/sisab/producao.py", line 1371, in obter_relatorio_producao
with criar_geckodriver() as driver:
└ <function criar_geckodriver at 0x7ffa1436a700>
File "/usr/local/lib/python3.8/contextlib.py", line [113](https://github.com/ImpulsoGov/etl/runs/7403356657?check_suite_focus=true#step:5:114), in __enter__
return next(self.gen)
│ └ <generator object criar_geckodriver at 0x7ffa1431d200>
└ <contextlib._GeneratorContextManager object at 0x7ffa14303640>
File "/home/appuser/.local/lib/python3.8/site-packages/impulso***/navegadores.py", line 101, in criar_geckodriver
driver = webdriver.Firefox(service=servico, options=opcoes)
│ │ │ └ <selenium.webdriver.firefox.options.Options object at 0x7ffa1424d040>
│ │ └ <selenium.webdriver.firefox.service.Service object at 0x7ffa14303430>
│ └ <class 'selenium.webdriver.firefox.webdriver.WebDriver'>
└ <module 'selenium.webdriver' from '/home/appuser/.local/lib/python3.8/site-packages/selenium/webdriver/__init__.py'>
File "/home/appuser/.local/lib/python3.8/site-packages/selenium/webdriver/firefox/webdriver.py", line 174, in __init__
self.service.start()
│ │ └ <function Service.start at 0x7ffa14466820>
│ └ <selenium.webdriver.firefox.service.Service object at 0x7ffa[143](https://github.com/ImpulsoGov/etl/runs/7403356657?check_suite_focus=true#step:5:144)03430>
└ <unprintable WebDriver object>
File "/home/appuser/.local/lib/python3.8/site-packages/selenium/webdriver/common/service.py", line 86, in start
raise WebDriverException(
└ <class 'selenium.common.exceptions.WebDriverException'>
selenium.common.exceptions.WebDriverException: Message: '' executable may have wrong permissions.
As habilitações do estabelecimentos de saúde são registradas no Sistema do Cadastro Nacional de Estabelecimentos de Saúde, e divulgadas mensalmente por meio do repositório FTP público do DataSUS (ftp://[email protected]/dissemin/publicos/CNES/200508_/Dados), nos arquivos de disseminação HB*.dbc
. Estes arquivos ainda não são armazenados no nosso banco de dados, mas seriam úteis, por exemplo, para realizar a quebra dos CAPS em linhas de cuidado e idades no projeto de saúde mental.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.