Description
Problem
The Python wrapper is finding every repository in the runfiles tree, creating a huge PYTHONPATH variable, and then crashing when it exceeds the system's env var limits.
I encountered this on Ubuntu 20.04, Python 3.8.
OSError: [Errno 7] Argument list too long: '/root/.cache/bazel/_bazel_root/70833c7af31404a35dcc581d457bd519/execroot/rivethealth_rivet/bazel-out/k8-fastbuild/bin/api/test_it/bin.runfiles/bazel_tools/tools/python/py3wrapper.sh'
A large number (hundreds) of external repositories is quite possible with Maven and npm projects. In my case, I have utility tools written in Python used in the runtime tree of a Node.js binary (that pulls in npm repositories).
Solution
Ideally, py_binary
would only add Python dependencies to the PYTHONPATH. Besides prevent a crash, it's also more efficient for loading modules.
Workarounds
import_all
An undocumented option --experimental_python_import_all_repositories=false
prevents automatically adding these repositories.
However, it requires specifying the imports
attribute, at least in some executions contexts, and of course the general Bazel ecosystem (e.g. rules_docker) doesn't do that.
usercustomize
Use usercustomize to change PYTHONPATH when execv is run.
~/.local/lib/python3.8/site-packages/usercustomize.py
import os
execv = os.execv
def _execv(*args, **kwargs):
try:
pythonpath = os.environ["PYTHONPATH"]
except KeyError:
pass
# remove unnecessary entries from pythonpath
# ...
os.environ["PYTHONPATH"] = pythonpath
return execv(*args, **kwargs)
os.execv = _execv