GithubHelp home page GithubHelp logo

impulsogov / etl Goto Github PK

View Code? Open in Web Editor NEW
10.0 10.0 1.0 21.43 MB

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.

Dockerfile 0.25% JavaScript 0.02% Python 99.56% Shell 0.17%

etl's People

Contributors

bcbernardo avatar biacunha avatar dependabot[bot] avatar fernandesbruna avatar gabriellearruda avatar maaottoni avatar silasmaverick avatar waltmatheus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

etl's Issues

Erro ao capturar RAAS-PS - ES 10/2016

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

Admitir filtros na captura de dados do SIASUS

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 subpacote `impulsoprevine`

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.

Adicionar ETL do Sistema de Informações de Mortalidade (SIM)

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 ETL dos arquivos de violência pessoal/autoprovocada do SINAN

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.

Refatorar capturas de relatórios de produção do SISAB

Contexto

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.

Escopo

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…).

Registrar erros na execução das capturas em uma tabela do banco de dados

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:

  • Qual foi a exceção ou código de erro.
  • Data e hora do erro.
  • Em que função o erro ocorreu.
  • Quais eram os parâmetros que a função de ETL recebeu e estava tentando rodar quando o erro ocorreu.

UUID mal formatado no ETL de relatórios de produção do SISAB

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')
# ...
Log completo: (clique para visualizar)
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: [{}]]

Extrair arquivos do FTP do DataSUS sem corromper

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.

(impulsoetl) Problema de permissão em capturas do SISAB com Selenium

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.

ETL de habilitações dos estabelecimentos de saúde (SCNES)

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.