Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EOFError during pytest session finish with pytest_xdist plugin #72

Open
junuMoon opened this issue May 16, 2024 · 2 comments · May be fixed by #75
Open

EOFError during pytest session finish with pytest_xdist plugin #72

junuMoon opened this issue May 16, 2024 · 2 comments · May be fixed by #75

Comments

@junuMoon
Copy link

cmd

pytest tests/test_model_follow_character_description.py -n 4

Env

  • OS: Linux
  • Python Version: 3.12.3
  • pytest Version: 8.1.1
  • pytest Plugins:
    • anyio-4.3.0
    • asyncio-0.23.6
    • xdist-3.6.1
    • repeat-0.9.3
    • deepeval-0.21.36
    • harvest-1.10.5

Error Traceback

============================================= test session starts ==============================================
platform linux -- Python 3.12.3, pytest-8.1.1, pluggy-1.5.0
rootdir: /mnt/raid/fran/kai
configfile: pytest.ini
plugins: anyio-4.3.0, asyncio-0.23.6, xdist-3.6.1, repeat-0.9.3, deepeval-0.21.36, harvest-1.10.5
asyncio: mode=Mode.STRICT
initialized: 4/4 workers/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/deepeval/__init__.py:42: UserWarning: You are using deepeval version 0.21.36, however version 0.21.42 is available. You should consider upgrading via the "pip install --upgrade deepeval" command.
  warnings.warn(
/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/deepeval/__init__.py:42: UserWarning: You are using deepeval version 0.21.36, however version 0.21.42 is available. You should consider upgrading via the "pip install --upgrade deepeval" command.
  warnings.warn(
/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/deepeval/__init__.py:42: UserWarning: You are using deepeval version 0.21.36, however version 0.21.42 is available. You should consider upgrading via the "pip install --upgrade deepeval" command.
  warnings.warn(
/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/deepeval/__init__.py:42: UserWarning: You are using deepeval version 0.21.36, however version 0.21.42 is available. You should consider upgrading via the "pip install --upgrade deepeval" command.
  warnings.warn(
4 workers [4 items]     
....                                                                                                     [100%]Running teardown with pytest sessionfinish...
Traceback (most recent call last):
  File "/mnt/raid/fran/miniconda3/bin/pytest", line 8, in <module>
    sys.exit(console_main())
             ^^^^^^^^^^^^^^
  File "/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/_pytest/config/__init__.py", line 197, in console_main
    code = main()
           ^^^^^^
  File "/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/_pytest/config/__init__.py", line 174, in main
    ret: Union[ExitCode, int] = config.hook.pytest_cmdline_main(
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/pluggy/_hooks.py", line 513, in __call__
    return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/pluggy/_manager.py", line 120, in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/pluggy/_callers.py", line 139, in _multicall
    raise exception.with_traceback(exception.__traceback__)
  File "/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/pluggy/_callers.py", line 103, in _multicall
    res = hook_impl.function(*args)
          ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/_pytest/main.py", line 332, in pytest_cmdline_main
    return wrap_session(config, _main)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/_pytest/main.py", line 320, in wrap_session
    config.hook.pytest_sessionfinish(
  File "/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/pluggy/_hooks.py", line 513, in __call__
    return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/pluggy/_manager.py", line 120, in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/pluggy/_callers.py", line 182, in _multicall
    return outcome.get_result()
           ^^^^^^^^^^^^^^^^^^^^
  File "/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/pluggy/_result.py", line 100, in get_result
    raise exc.with_traceback(exc.__traceback__)
  File "/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/pluggy/_callers.py", line 167, in _multicall
    teardown.throw(outcome._exception)
  File "/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/_pytest/logging.py", line 871, in pytest_sessionfinish
    return (yield)
            ^^^^^
  File "/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/pluggy/_callers.py", line 167, in _multicall
    teardown.throw(outcome._exception)
  File "/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/_pytest/terminal.py", line 866, in pytest_sessionfinish
    result = yield
             ^^^^^
  File "/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/pluggy/_callers.py", line 167, in _multicall
    teardown.throw(outcome._exception)
  File "/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/_pytest/warnings.py", line 140, in pytest_sessionfinish
    return (yield)
            ^^^^^
  File "/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/pluggy/_callers.py", line 103, in _multicall
    res = hook_impl.function(*args)
          ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/mnt/raid/fran/kai/tests/conftest.py", line 82, in pytest_sessionfinish
    session_results_df = get_session_results_df(session)
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/pytest_harvest/plugin.py", line 246, in get_session_results_df
    possibly_restore_xdist_workers_structs(session_or_request)
  File "/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/pytest_harvest/plugin.py", line 476, in possibly_restore_xdist_workers_structs
    workers_saved_material = session.config.hook.pytest_harvest_xdist_load()
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/pluggy/_hooks.py", line 513, in __call__
    return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/mnt/raid/fran/miniconda3/lib/python3.12/site-packages/pluggy/_manager.py", line
@AlmogBaku
Copy link

AlmogBaku commented Sep 22, 2024

I found out that cloudpickle can solve this issue. I recommend the library will switch to it :) cc @smarie

# conftest.py
import cloudpickle  # type: ignore
from typing import OrderedDict, Dict, Any
from logging import warning
from pathlib import Path
from shutil import rmtree

# ## Xdist harvesting using cloudpickle instead of pytest-harvest's default pickling
# ## This is useful when the harvested objects are not serializable by pytest-harvest's default pickling.
RESULTS_PATH = Path('./.xdist_harvested/')


def pytest_harvest_xdist_init() -> bool:
    if RESULTS_PATH.exists():
        rmtree(RESULTS_PATH)
    RESULTS_PATH.mkdir(exist_ok=False)
    return True


def pytest_harvest_xdist_worker_dump(worker_id: str, session_items: Any, fixture_store: OrderedDict[Any, Any]) -> bool:
    with open(RESULTS_PATH / f'{worker_id}.pkl', 'wb') as f:
        try:
            cloudpickle.dump((session_items, fixture_store), f)
        except Exception as e:
            warning(f"Error while pickling worker {worker_id}'s harvested results: [{e.__class__}] {e}")
    return True


def pytest_harvest_xdist_load() -> Dict[str, Any]:
    workers_saved_material = dict()
    for pkl_file in RESULTS_PATH.glob('*.pkl'):
        wid = pkl_file.stem
        with pkl_file.open('rb') as f:
            workers_saved_material[wid] = cloudpickle.load(f)
    return workers_saved_material


def pytest_harvest_xdist_cleanup() -> bool:
    rmtree(RESULTS_PATH)
    return True

smarie pushed a commit that referenced this issue Sep 30, 2024
…`pytest-xdist plugin` and `-n` option activated. Fixed #72
@smarie
Copy link
Owner

smarie commented Sep 30, 2024

Hi both, thanks a lot @junuMoon for finding this issue and @AlmogBaku for finding a solution !

I cannot reproduce the issue on my side, so @junuMoon can you please

Thanks a lot !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants