diff --git a/mitmproxy/addons/script.py b/mitmproxy/addons/script.py index 1c37e4a43..12586d327 100644 --- a/mitmproxy/addons/script.py +++ b/mitmproxy/addons/script.py @@ -39,6 +39,17 @@ def load_script(path: str) -> Optional[types.ModuleType]: loader.exec_module(m) if not getattr(m, "name", None): m.name = path # type: ignore + except ImportError as e: + err_msg = str(e) + if getattr(sys, "frozen", False): + err_msg = ( + f"{err_msg}. \n" + f"Note that mitmproxy's binaries include their own Python environment. " + f"If your addon requires the installation of additional dependencies, " + f"please install mitmproxy from PyPI " + f"(https://docs.mitmproxy.org/stable/overview-installation/#installation-from-the-python-package-index-pypi)." + ) + script_error_handler(path, e, msg=err_msg) except Exception as e: script_error_handler(path, e, msg=str(e)) finally: diff --git a/test/mitmproxy/addons/test_script.py b/test/mitmproxy/addons/test_script.py index fba36a556..0971fa0e9 100644 --- a/test/mitmproxy/addons/test_script.py +++ b/test/mitmproxy/addons/test_script.py @@ -123,6 +123,14 @@ class TestScript: await caplog_async.await_log("error.py") sc.done() + async def test_import_error(self, monkeypatch, tdata, caplog): + monkeypatch.setattr(sys, "frozen", True, raising=False) + script.Script( + tdata.path("mitmproxy/data/addonscripts/import_error.py"), + False, + ) + assert "Note that mitmproxy's binaries include their own Python environment" in caplog.text + async def test_optionexceptions(self, tdata, caplog_async): with taddons.context() as tctx: sc = script.Script( diff --git a/test/mitmproxy/data/addonscripts/import_error.py b/test/mitmproxy/data/addonscripts/import_error.py new file mode 100644 index 000000000..e868bcc34 --- /dev/null +++ b/test/mitmproxy/data/addonscripts/import_error.py @@ -0,0 +1 @@ +import nonexistent