pytest-dev / pytest

The pytest framework makes it easy to write small tests, yet scales to support complex functional testing
https://pytest.org
MIT License
12.15k stars 2.69k forks source link

macOS: OSError: [Errno 24] Too many open files #11088

Closed jamesbraza closed 1 year ago

jamesbraza commented 1 year ago

I have 173 tests and 57 subtests, and with macOS Monterey v12.6 from zsh, I keep hitting this error, after ~20 of the test cases:

OSError: [Errno 24] Too many open files: '/path/to/repo/venv/lib/python3.10/site-packages/pygments/__init__.py'

What's interesting is this error does not happen when using the same exact set up in:

I can fix the problem on my Mac using this command:

ulimit -n unlimited

Every time I power cycle my computer, I need to re-run this command.

I opened this issue to ask, can pytest do anything about this? Why is it happening?

More Context

> pytest test
=============================================================================================================== test session starts ===============================================================================================================
platform darwin -- Python 3.10.9, pytest-7.3.1, pluggy-1.0.0
rootdir: /path/to/repo/test
configfile: pyproject.toml
plugins: pyfakefs-5.2.2, subtests-0.11.0, mock-3.10.0
collected 72 items
repo/test/test_1.py .........................................                                                                                                                                                                          [ 56%]
repo/test/test_2.py ..........                                                                                                                                                                                               [ 70%]
repo/test/test_3.py ...........                                                                                                                                                                                                  [ 86%]
repo/test/test_4.py ....EEEEEE
Traceback ```python Traceback (most recent call last): File "/path/to/repo/venv/bin/pytest", line 8, in sys.exit(console_main()) File "/path/to/repo/venv/lib/python3.10/site-packages/_pytest/config/__init__.py", line 189, in console_main code = main() File "/path/to/repo/venv/lib/python3.10/site-packages/_pytest/config/__init__.py", line 166, in main ret: Union[ExitCode, int] = config.hook.pytest_cmdline_main( File "/path/to/repo/venv/lib/python3.10/site-packages/pluggy/_hooks.py", line 265, in __call__ return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult) File "/path/to/repo/venv/lib/python3.10/site-packages/pluggy/_manager.py", line 80, in _hookexec return self._inner_hookexec(hook_name, methods, kwargs, firstresult) File "/path/to/repo/venv/lib/python3.10/site-packages/pluggy/_callers.py", line 60, in _multicall return outcome.get_result() File "/path/to/repo/venv/lib/python3.10/site-packages/pluggy/_result.py", line 60, in get_result raise ex[1].with_traceback(ex[2]) File "/path/to/repo/venv/lib/python3.10/site-packages/pluggy/_callers.py", line 39, in _multicall res = hook_impl.function(*args) File "/path/to/repo/venv/lib/python3.10/site-packages/_pytest/main.py", line 316, in pytest_cmdline_main return wrap_session(config, _main) File "/path/to/repo/venv/lib/python3.10/site-packages/_pytest/main.py", line 304, in wrap_session config.hook.pytest_sessionfinish( File "/path/to/repo/venv/lib/python3.10/site-packages/pluggy/_hooks.py", line 265, in __call__ return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult) File "/path/to/repo/venv/lib/python3.10/site-packages/pluggy/_manager.py", line 80, in _hookexec return self._inner_hookexec(hook_name, methods, kwargs, firstresult) File "/path/to/repo/venv/lib/python3.10/site-packages/pluggy/_callers.py", line 55, in _multicall gen.send(outcome) File "/path/to/repo/venv/lib/python3.10/site-packages/_pytest/terminal.py", line 822, in pytest_sessionfinish self.config.hook.pytest_terminal_summary( File "/path/to/repo/venv/lib/python3.10/site-packages/pluggy/_hooks.py", line 265, in __call__ return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult) File "/path/to/repo/venv/lib/python3.10/site-packages/pluggy/_manager.py", line 80, in _hookexec return self._inner_hookexec(hook_name, methods, kwargs, firstresult) File "/path/to/repo/venv/lib/python3.10/site-packages/pluggy/_callers.py", line 60, in _multicall return outcome.get_result() File "/path/to/repo/venv/lib/python3.10/site-packages/pluggy/_result.py", line 60, in get_result raise ex[1].with_traceback(ex[2]) File "/path/to/repo/venv/lib/python3.10/site-packages/pluggy/_callers.py", line 34, in _multicall next(gen) # first yield File "/path/to/repo/venv/lib/python3.10/site-packages/_pytest/terminal.py", line 836, in pytest_terminal_summary self.summary_errors() File "/path/to/repo/venv/lib/python3.10/site-packages/_pytest/terminal.py", line 1035, in summary_errors self._outrep_summary(rep) File "/path/to/repo/venv/lib/python3.10/site-packages/_pytest/terminal.py", line 1038, in _outrep_summary rep.toterminal(self._tw) File "/path/to/repo/venv/lib/python3.10/site-packages/_pytest/reports.py", line 89, in toterminal longrepr_terminal.toterminal(out) File "/path/to/repo/venv/lib/python3.10/site-packages/_pytest/_code/code.py", line 1039, in toterminal element[0].toterminal(tw) File "/path/to/repo/venv/lib/python3.10/site-packages/_pytest/_code/code.py", line 1069, in toterminal entry.toterminal(tw) File "/path/to/repo/venv/lib/python3.10/site-packages/_pytest/_code/code.py", line 1164, in toterminal self._write_entry_lines(tw) File "/path/to/repo/venv/lib/python3.10/site-packages/_pytest/_code/code.py", line 1146, in _write_entry_lines tw._write_source(source_lines, indents) File "/path/to/repo/venv/lib/python3.10/site-packages/_pytest/_io/terminalwriter.py", line 192, in _write_source new_lines = self._highlight(source).splitlines() File "/path/to/repo/venv/lib/python3.10/site-packages/_pytest/_io/terminalwriter.py", line 203, in _highlight from pygments.formatters.terminal import TerminalFormatter File "", line 1027, in _find_and_load File "", line 1006, in _find_and_load_unlocked File "", line 688, in _load_unlocked File "", line 879, in exec_module File "", line 1016, in get_code File "", line 1073, in get_data OSError: [Errno 24] Too many open files: '/path/to/repo/venv/lib/python3.10/site-packages/pygments/__init__.py' ```
pip list ```shell > pip list Package Version Editable project location ---------------------------- ------------------- ----------------------------------------- appnope 0.1.3 astroid 2.15.5 asttokens 2.2.1 attrs 23.1.0 backcall 0.2.0 black 23.3.0 bleach 6.0.0 cachetools 5.3.1 certifi 2023.5.7 cfgv 3.3.1 chardet 5.1.0 charset-normalizer 3.1.0 click 8.1.3 colorama 0.4.6 coverage 7.2.5 decorator 5.1.1 dill 0.3.6 distlib 0.3.6 docformatter 1.7.0 docutils 0.20 exceptiongroup 1.1.1 executing 1.2.0 filelock 3.12.0 flake8 6.0.0 Flake8-pyproject 1.2.3 flake8-requirements 1.7.8 identify 2.5.24 idna 3.4 importlib-metadata 6.6.0 iniconfig 2.0.0 ipython 8.13.2 isort 5.12.0 jaraco.classes 3.2.3 jedi 0.18.2 keyring 23.13.1 lazy-object-proxy 1.9.0 markdown-it-py 2.2.0 matplotlib-inline 0.1.6 mccabe 0.7.0 mdurl 0.1.2 more-itertools 9.1.0 mypy 1.3.0 mypy-extensions 1.0.0 nodeenv 1.8.0 numpy 1.24.3 OpenOPC-Python3x 1.3.1 packaging 23.1 pandas 2.0.1 parso 0.8.3 pathspec 0.11.1 pexpect 4.8.0 Phidget22 1.14.20230331 pickleshare 0.7.5 pip 22.3.1 pkginfo 1.9.6 platformdirs 3.5.1 pluggy 1.0.0 pre-commit 3.3.1 prompt-toolkit 3.0.38 ptyprocess 0.7.0 pure-eval 0.2.2 pycodestyle 2.10.0 pyenchant 3.2.2 pyfakefs 5.2.2 pyflakes 3.0.1 Pygments 2.15.1 pylint 2.17.4 pymodbus 3.2.0 pyproject_api 1.5.1 Pyro4 4.82 pyserial 3.5 pytest 7.3.1 pytest-mock 3.10.0 pytest-subtests 0.11.0 python-dateutil 2.8.2 pytz 2023.3 PyYAML 6.0 readme-renderer 37.3 requests 2.30.0 requests-toolbelt 1.0.0 rfc3986 2.0.0 rich 13.3.5 ruff 0.0.270 serpent 1.41 setuptools 65.5.0 setuptools-scm 7.1.0 six 1.16.0 stack-data 0.6.2 INTERNAL PACKAGES REDACTED tomli 2.0.1 tomlkit 0.11.8 tox 4.6.0 traitlets 5.9.0 twine 4.0.2 types-setuptools 67.7.0.2 typing_extensions 4.5.0 tzdata 2023.3 untokenize 0.1.1 urllib3 2.0.2 virtualenv 20.23.0 wcwidth 0.2.6 webencodings 0.5.1 wrapt 1.15.0 zipp 3.15.0 ```
RonnyPfannschmidt commented 1 year ago

It's unclear what's the origin of the number of open files, please trying with --tb-style=native to see a better error

jamesbraza commented 1 year ago

I think it was --tb=native, and wow that revealed the real traceback!

The tests were failing due to this: https://stackoverflow.com/questions/15435652/python-does-not-release-filehandles-to-logfile

  1. Prior tests were asynchronously creating and using logging.FileHandlers
  2. The file descriptors weren't being manually closed (per that stack overflow post)
  3. After enough test cases, the code hit the open file descriptor limit

Case closed, thank you! Nothing pytest can handle, unless you think so (and feel free to re-open if so).

CanD42 commented 5 months ago

This happen now to me now with Python 3.12.2 and pytest 8.2.1 so I rolled back to pytest 8.1.2 where the problem isn't present. I can workound it locally with "ulimit -n unlimited" but not on the build server. So there must be a change in pytest 8.2.1. which is causing it. Is there a way to improve the tests to prevent this?

bluetech commented 5 months ago

@CanD42 my first suggestion is to ascertain what is consuming all of these file descriptors. The lsof or lsfd commands are good for this.

CanD42 commented 5 months ago

@bluetech it seems to be fixed with pytest 8.2.2. Thanks