New submission from Igor Filatov: ensurepip runs pip with a function that discards the result code that pip produces:
def _run_pip(args, additional_paths=None): # ... pip.main(args) pip.main() is designed not to raise command exceptions. Instead it returns exit codes which are to be passed to sys.exit(). Since ensurepip does not process the return value of pip.main() in any way, python -m ensurepip always exits with 0 on such exceptions (even though there's a stack trace, printing of which is handled by pip). EC should be 0 only in case of success. This is an issue in venv because it runs ensurepip in a subprocess and cannot detect a failure: def _setup_pip(self, context): # ... cmd = [context.env_exe, '-Im', 'ensurepip', '--upgrade', '--default-pip'] subprocess.check_output(cmd, stderr=subprocess.STDOUT) And this leads to broken venvs in some cases. The easiest way to reproduce: $ mkdir venv-test $ cd venv-test/ $ echo garbage > setup.cfg $ python3 -m venv broken $ broken/bin/pip bash: broken/bin/pip: No such file or directory There are no errors until you need pip. The culprit is this: $ broken/bin/python -Im ensurepip --upgrade --default-pip Ignoring indexes: https://pypi.python.org/simple Collecting setuptools Collecting pip Collecting pkg_resources Installing collected packages: setuptools, pip, pkg-resources Exception: Traceback (most recent call last): File "/tmp/tmpgjpdbf_e/pip-8.1.1-py2.py3-none-any.whl/pip/basecommand.py", line 209, in main status = self.run(options, args) File "/tmp/tmpgjpdbf_e/pip-8.1.1-py2.py3-none-any.whl/pip/commands/install.py", line 335, in run prefix=options.prefix_path, File "/tmp/tmpgjpdbf_e/pip-8.1.1-py2.py3-none-any.whl/pip/req/req_set.py", line 732, in install **kwargs File "/tmp/tmpgjpdbf_e/pip-8.1.1-py2.py3-none-any.whl/pip/req/req_install.py", line 837, in install self.move_wheel_files(self.source_dir, root=root, prefix=prefix) File "/tmp/tmpgjpdbf_e/pip-8.1.1-py2.py3-none-any.whl/pip/req/req_install.py", line 1039, in move_wheel_files isolated=self.isolated, File "/tmp/tmpgjpdbf_e/pip-8.1.1-py2.py3-none-any.whl/pip/wheel.py", line 247, in move_wheel_files prefix=prefix, File "/tmp/tmpgjpdbf_e/pip-8.1.1-py2.py3-none-any.whl/pip/locations.py", line 141, in distutils_scheme d.parse_config_files() File "/usr/lib/python3.5/distutils/dist.py", line 395, in parse_config_files parser.read(filename) File "/usr/lib/python3.5/configparser.py", line 696, in read self._read(fp, filename) File "/usr/lib/python3.5/configparser.py", line 1077, in _read raise MissingSectionHeaderError(fpname, lineno, line) configparser.MissingSectionHeaderError: File contains no section headers. file: 'setup.cfg', line: 1 'garbage\n' But any other exception during pip any_command would've had the same effect. This is hard to diagnose because no output is produced by subprocess due to the exception. ensurepip should propagate the code returned by pip and pass it to sys.exit(). Alternatively ensurepip can have it's own EC for cases when pip.main(args) != 0. ---------- components: Library (Lib) messages: 301367 nosy: Igor Filatov priority: normal severity: normal status: open title: ensurepip discards pip's return code which leads to broken venvs type: behavior versions: Python 3.4, Python 3.5, Python 3.6, Python 3.7 _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue31351> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com