pytestでpytest-profilingを使っているときにでる ValueError: Plugin already registered
概要
$ make pytest if [ -z 1588034257 ] || [ 1587982138 -ge 1588034257 ]; then \ docker build . -t test; \ else \ echo "Docker container image is ready up to date."; \ fi Docker container image is ready up to date. docker run --rm -it test pytest --color=no tests/ Traceback (most recent call last): File "/usr/local/lib/python3.8/site-packages/_pytest/config/__init__.py", line 495, in _importconftest return self._conftestpath2mod[key] KeyError: PosixPath('/test/conftest.py') During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/usr/local/bin/pytest", line 8, in <module> sys.exit(main()) File "/usr/local/lib/python3.8/site-packages/_pytest/config/__init__.py", line 105, in main config = _prepareconfig(args, plugins) File "/usr/local/lib/python3.8/site-packages/_pytest/config/__init__.py", line 257, in _prepareconfig return pluginmanager.hook.pytest_cmdline_parse( File "/usr/local/lib/python3.8/site-packages/pluggy/hooks.py", line 286, in __call__ return self._hookexec(self, self.get_hookimpls(), kwargs) File "/usr/local/lib/python3.8/site-packages/pluggy/manager.py", line 93, in _hookexec return self._inner_hookexec(hook, methods, kwargs) File "/usr/local/lib/python3.8/site-packages/pluggy/manager.py", line 84, in <lambda> self._inner_hookexec = lambda hook, methods, kwargs: hook.multicall( File "/usr/local/lib/python3.8/site-packages/pluggy/callers.py", line 203, in _multicall gen.send(outcome) File "/usr/local/lib/python3.8/site-packages/_pytest/helpconfig.py", line 90, in pytest_cmdline_parse config = outcome.get_result() File "/usr/local/lib/python3.8/site-packages/pluggy/callers.py", line 80, in get_result raise ex[1].with_traceback(ex[2]) File "/usr/local/lib/python3.8/site-packages/pluggy/callers.py", line 187, in _multicall res = hook_impl.function(*args) File "/usr/local/lib/python3.8/site-packages/_pytest/config/__init__.py", line 836, in pytest_cmdline_parse self.parse(args) File "/usr/local/lib/python3.8/site-packages/_pytest/config/__init__.py", line 1044, in parse self._preparse(args, addopts=addopts) File "/usr/local/lib/python3.8/site-packages/_pytest/config/__init__.py", line 1001, in _preparse self.hook.pytest_load_initial_conftests( File "/usr/local/lib/python3.8/site-packages/pluggy/hooks.py", line 286, in __call__ return self._hookexec(self, self.get_hookimpls(), kwargs) File "/usr/local/lib/python3.8/site-packages/pluggy/manager.py", line 93, in _hookexec return self._inner_hookexec(hook, methods, kwargs) File "/usr/local/lib/python3.8/site-packages/pluggy/manager.py", line 84, in <lambda> self._inner_hookexec = lambda hook, methods, kwargs: hook.multicall( File "/usr/local/lib/python3.8/site-packages/pluggy/callers.py", line 208, in _multicall return outcome.get_result() File "/usr/local/lib/python3.8/site-packages/pluggy/callers.py", line 80, in get_result raise ex[1].with_traceback(ex[2]) File "/usr/local/lib/python3.8/site-packages/pluggy/callers.py", line 187, in _multicall res = hook_impl.function(*args) File "/usr/local/lib/python3.8/site-packages/_pytest/config/__init__.py", line 899, in pytest_load_initial_conftests self.pluginmanager._set_initial_conftests(early_config.known_args_namespace) File "/usr/local/lib/python3.8/site-packages/_pytest/config/__init__.py", line 441, in _set_initial_conftests self._try_load_conftest(anchor) File "/usr/local/lib/python3.8/site-packages/_pytest/config/__init__.py", line 447, in _try_load_conftest self._getconftestmodules(anchor) File "/usr/local/lib/python3.8/site-packages/_pytest/config/__init__.py", line 473, in _getconftestmodules mod = self._importconftest(conftestpath) File "/usr/local/lib/python3.8/site-packages/_pytest/config/__init__.py", line 520, in _importconftest self.consider_conftest(mod) File "/usr/local/lib/python3.8/site-packages/_pytest/config/__init__.py", line 575, in consider_conftest self.register(conftestmodule, name=conftestmodule.__file__) File "/usr/local/lib/python3.8/site-packages/_pytest/config/__init__.py", line 386, in register self.consider_module(plugin) File "/usr/local/lib/python3.8/site-packages/_pytest/config/__init__.py", line 581, in consider_module self._import_plugin_specs(getattr(mod, "pytest_plugins", [])) File "/usr/local/lib/python3.8/site-packages/_pytest/config/__init__.py", line 586, in _import_plugin_specs self.import_plugin(import_spec) File "/usr/local/lib/python3.8/site-packages/_pytest/config/__init__.py", line 629, in import_plugin self.register(mod, modname) File "/usr/local/lib/python3.8/site-packages/_pytest/config/__init__.py", line 379, in register ret = super().register(plugin, name) File "/usr/local/lib/python3.8/site-packages/pluggy/manager.py", line 104, in register raise ValueError( ValueError: Plugin already registered: pytest_profiling=<module 'pytest_profiling' from '/usr/local/lib/python3.8/site-packages/pytest_profiling.py'> {'140074314182224': <_pytest.config.PytestPluginManager object at 0x7f6597bd2e50>, 'pytestconfig': <_pytest.config.Config object at 0x7f6597170220>, 'mark': <module '_pytest.mark' from '/usr/local/lib/python3.8/site-packages/_pytest/mark/__init__.py'>, 'main': <module '_pytest.main' from '/usr/local/lib/python3.8/site-packages/_pytest/main.py'>, 'runner': <module '_pytest.runner' from '/usr/local/lib/python3.8/site-packages/_pytest/runner.py'>, 'fixtures': <module '_pytest.fixtures' from '/usr/local/lib/python3.8/site-packages/_pytest/fixtures.py'>, 'helpconfig': <module '_pytest.helpconfig' from '/usr/local/lib/python3.8/site-packages/_pytest/helpconfig.py'>, 'python': <module '_pytest.python' from '/usr/local/lib/python3.8/site-packages/_pytest/python.py'>, 'terminal': <module '_pytest.terminal' from '/usr/local/lib/python3.8/site-packages/_pytest/terminal.py'>, 'debugging': <module '_pytest.debugging' from '/usr/local/lib/python3.8/site-packages/_pytest/debugging.py'>, 'unittest': <module '_pytest.unittest' from '/usr/local/lib/python3.8/site-packages/_pytest/unittest.py'>, 'capture': <module '_pytest.capture' from '/usr/local/lib/python3.8/site-packages/_pytest/capture.py'>, 'skipping': <module '_pytest.skipping' from '/usr/local/lib/python3.8/site-packages/_pytest/skipping.py'>, 'tmpdir': <module '_pytest.tmpdir' from '/usr/local/lib/python3.8/site-packages/_pytest/tmpdir.py'>, 'monkeypatch': <module '_pytest.monkeypatch' from '/usr/local/lib/python3.8/site-packages/_pytest/monkeypatch.py'>, 'recwarn': <module '_pytest.recwarn' from '/usr/local/lib/python3.8/site-packages/_pytest/recwarn.py'>, 'pastebin': <module '_pytest.pastebin' from '/usr/local/lib/python3.8/site-packages/_pytest/pastebin.py'>, 'nose': <module '_pytest.nose' from '/usr/local/lib/python3.8/site-packages/_pytest/nose.py'>, 'assertion': <module '_pytest.assertion' from '/usr/local/lib/python3.8/site-packages/_pytest/assertion/__init__.py'>, 'junitxml': <module '_pytest.junitxml' from '/usr/local/lib/python3.8/site-packages/_pytest/junitxml.py'>, 'resultlog': <module '_pytest.resultlog' from '/usr/local/lib/python3.8/site-packages/_pytest/resultlog.py'>, 'doctest': <module '_pytest.doctest' from '/usr/local/lib/python3.8/site-packages/_pytest/doctest.py'>, 'cacheprovider': <module '_pytest.cacheprovider' from '/usr/local/lib/python3.8/site-packages/_pytest/cacheprovider.py'>, 'freeze_support': <module '_pytest.freeze_support' from '/usr/local/lib/python3.8/site-packages/_pytest/freeze_support.py'>, 'setuponly': <module '_pytest.setuponly' from '/usr/local/lib/python3.8/site-packages/_pytest/setuponly.py'>, 'setupplan': <module '_pytest.setupplan' from '/usr/local/lib/python3.8/site-packages/_pytest/setupplan.py'>, 'stepwise': <module '_pytest.stepwise' from '/usr/local/lib/python3.8/site-packages/_pytest/stepwise.py'>, 'warnings': <module '_pytest.warnings' from '/usr/local/lib/python3.8/site-packages/_pytest/warnings.py'>, 'logging': <module '_pytest.logging' from '/usr/local/lib/python3.8/site-packages/_pytest/logging.py'>, 'reports': <module '_pytest.reports' from '/usr/local/lib/python3.8/site-packages/_pytest/reports.py'>, 'faulthandler': <module '_pytest.faulthandler' from '/usr/local/lib/python3.8/site-packages/_pytest/faulthandler.py'>, 'profiling': <module 'pytest_profiling' from '/usr/local/lib/python3.8/site-packages/pytest_profiling.py'>, 'capturemanager': <CaptureManager _method='fd' _global_capturing=<MultiCapture out=<FDCapture 1 oldfd=5 _state='started' tmpfile=<_pytest.capture.EncodedFile object at 0x7f6596ed0220>> err=<FDCapture 2 oldfd=6 _state='started' tmpfile=<_pytest.capture.EncodedFile object at 0x7f6596ed02b0>> in_=<FDCapture 0 oldfd=3 _state='started' tmpfile=<_io.TextIOWrapper name='/dev/null' mode='r' encoding='UTF-8'>> _state='started' _in_suspended=False> _capture_fixture=None>, '/test/conftest.py': <module 'conftest' from '/test/conftest.py'>} make: *** [Makefile:26: pytest] Error 1/conftest.py'>} make: *** [Makefile:26: pytest] Error 1
とりあえずpytest-profilingを無効にして、testを行えるようにしようと思ったが、conftest.pyを消してdockerイメージをビルドしても直らなかった。
.pyc
をすべて消す方法は効かなかった
https://github.com/pytest-dev/pytest/issues/3112#issuecomment-404979798
Docker imageを消してから作り直してみても効かなかった
dangling image を消して再度pytestを動かしたら治った
$ docker image prune
疑問
docker rmi
では解決せず、docker image prune
では解決したことから、原因は中間イメージレイヤの変更であると考えられるdocker rmi
では中間イメージレイヤは削除されないと仮定するとこういう演繹ができる
しかし、中間レイヤは読み込み専用のはず
- ファイルを変更するたびに毎回イメージをビルドし直す方法をとっていたが、Dockerfileの
COPY
コマンド以降にはENV
コマンドしかないのでファイルシステムに変更はないはず - なぜ中間イメージレイヤが変更されたのか?
- 再度conftest.pyを配置してイメージをビルドしても同じエラーが出た。以前は使用可能だった。
2020-04-28 13:40 追記
- conftest.pyを消去してもprofileは動作したので、
If a plugin is installed, pytest automatically finds and integrates it, there is no need to activate it.
や
Requiring plugins using a pytest_plugins variable in non-root conftest.py files is deprecated. See full explanation in the Writing plugins section.
が関係しそう。conftest.pyはrootに配置しているはずではあるが。