title: Python 3 `venv` and the `wheel` package
body: <p>Starting with python3.8, I noticed that the <code>wheel</code> package seems to be required to <code>pip install</code> packages without errors (at least they look like errors, but behave like warnings).</p>
  <p><em>Note: in all of my examples, I am cleaning up in between by deactivating my environment, removing the environment, and clearing my pip cache:</em></p>
  <pre class="lang-sh prettyprint-override"><code>deactivate
  rm test_env/ -rf
  rm ~/.cache/pip/ -rf
  </code></pre>
  <h2>Example 1: The problem</h2>
  <pre class="lang-sh prettyprint-override"><code>python3.8 -m venv test_env
  source test_env/bin/activate
  pip install markuppy
  </code></pre>
  <p>I get the following output:</p>
  <pre><code>Collecting markuppy
    Downloading MarkupPy-1.14.tar.gz (6.8 kB)
  Building wheels for collected packages: markuppy
    Building wheel for markuppy (setup.py) ... error
    ERROR: Command errored out with exit status 1:
     command: /home/k/test_env/bin/python3.8 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '&quot;'&quot;'/tmp/pip-install-tfm9bgxv/markuppy/setup.py'&quot;'&quot;'; __file__='&quot;'&quot;'/tmp/pip-install-tfm9bgxv/markuppy/setup.py'&quot;'&quot;';f=getattr(tokenize, '&quot;'&quot;'open'&quot;'&quot;', open)(__file__);code=f.read().replace('&quot;'&quot;'\r\n'&quot;'&quot;', '&quot;'&quot;'\n'&quot;'&quot;');f.close();exec(compile(code, __file__, '&quot;'&quot;'exec'&quot;'&quot;'))' bdist_wheel -d /tmp/pip-wheel-cpx9gxcn
         cwd: /tmp/pip-install-tfm9bgxv/markuppy/
    Complete output (6 lines):
    usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
       or: setup.py --help [cmd1 cmd2 ...]
       or: setup.py --help-commands
       or: setup.py cmd --help
    
    error: invalid command 'bdist_wheel'
    ----------------------------------------
    ERROR: Failed building wheel for markuppy
    Running setup.py clean for markuppy
  Failed to build markuppy
  Installing collected packages: markuppy
      Running setup.py install for markuppy ... done
  Successfully installed markuppy-1.14
  </code></pre>
  <p>It errored because there is no <code>wheel</code> package installed. This has been addressed in other posts on SO.</p>
  <h2>Example 2: Fixing the problem by installing <code>wheel</code> into the venv</h2>
  <p>If I install the <code>wheel</code> package directly after creating a new venv, this does not happen:</p>
  <pre class="lang-sh prettyprint-override"><code>python3.8 -m venv test_env
  source test_env/bin/activate
  pip install wheel
  pip install markuppy
  </code></pre>
  <p>Output:</p>
  <pre><code>Collecting markuppy
    Using cached MarkupPy-1.14.tar.gz (6.8 kB)
  Building wheels for collected packages: markuppy
    Building wheel for markuppy (setup.py) ... done
    Created wheel for markuppy: filename=MarkupPy-1.14-py3-none-any.whl size=7413 sha256=52b3e5c3e317ae21724acd871fe3deb85dde9df305b20d16f2c5592c43b11e91
    Stored in directory: /home/k/.cache/pip/wheels/95/13/60/31c9d5f4cd012e491aeac154ef8b0ec964916523623eb02f0b
  Successfully built markuppy
  Installing collected packages: markuppy
  Successfully installed markuppy-1.14
  </code></pre>
  <p>This also works given a <code>requirements.txt</code> file.</p>
  <p><code>requirements.txt</code>:</p>
  <pre><code>markuppy
  </code></pre>
  <pre class="lang-sh prettyprint-override"><code>python3.8 -m venv test_env
  source test_env/bin/activate
  pip install wheel
  pip install -r requirements.txt
  </code></pre>
  <p>Output:</p>
  <pre><code>Collecting markuppy
    Using cached MarkupPy-1.14.tar.gz (6.8 kB)
  Building wheels for collected packages: markuppy
    Building wheel for markuppy (setup.py) ... done
    Created wheel for markuppy: filename=MarkupPy-1.14-py3-none-any.whl size=7413 sha256=52b3e5c3e317ae21724acd871fe3deb85dde9df305b20d16f2c5592c43b11e91
    Stored in directory: /home/k/.cache/pip/wheels/95/13/60/31c9d5f4cd012e491aeac154ef8b0ec964916523623eb02f0b
  Successfully built markuppy
  Installing collected packages: markuppy
  Successfully installed markuppy-1.14
  </code></pre>
  <h2>Example 3: Adding the <code>wheel</code> package to <code>requirements.txt</code> does not help</h2>
  <p>It's important to know that if you place the <code>wheel</code> package into the requirements.txt file, and do not install it separately, you get the same problem as in Example 1:</p>
  <p><code>requirements.txt</code>:</p>
  <pre><code>wheel
  markuppy
  </code></pre>
  <pre class="lang-sh prettyprint-override"><code>python3.8 -m venv test_env
  source test_env/bin/activate
  pip install -r requirements.txt
  </code></pre>
  <p>Output:</p>
  <pre><code>Collecting wheel
    Downloading wheel-0.37.0-py2.py3-none-any.whl (35 kB)
  Collecting markuppy
    Downloading MarkupPy-1.14.tar.gz (6.8 kB)
  Building wheels for collected packages: markuppy
    Building wheel for markuppy (setup.py) ... error
    ERROR: Command errored out with exit status 1:
     command: /home/k/test_env/bin/python3 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '&quot;'&quot;'/tmp/pip-install-z7cqzaej/markuppy/setup.py'&quot;'&quot;'; __file__='&quot;'&quot;'/tmp/pip-install-z7cqzaej/markuppy/setup.py'&quot;'&quot;';f=getattr(tokenize, '&quot;'&quot;'open'&quot;'&quot;', open)(__file__);code=f.read().replace('&quot;'&quot;'\r\n'&quot;'&quot;', '&quot;'&quot;'\n'&quot;'&quot;');f.close();exec(compile(code, __file__, '&quot;'&quot;'exec'&quot;'&quot;'))' bdist_wheel -d /tmp/pip-wheel-kw3_8ayt
         cwd: /tmp/pip-install-z7cqzaej/markuppy/
    Complete output (6 lines):
    usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
       or: setup.py --help [cmd1 cmd2 ...]
       or: setup.py --help-commands
       or: setup.py cmd --help
    
    error: invalid command 'bdist_wheel'
    ----------------------------------------
    ERROR: Failed building wheel for markuppy
    Running setup.py clean for markuppy
  Failed to build markuppy
  Installing collected packages: wheel, markuppy
      Running setup.py install for markuppy ... done
  Successfully installed markuppy-1.14 wheel-0.37.0
  </code></pre>
  <p>Wheel installed properly, but was not there in time to install the <code>markuppy</code> package.</p>
  <h2>Example 4: Installing <code>wheel</code> at the system level does not help</h2>
  <p>If I install the <code>wheel</code> package directly into the system itself, the venv that was created does not have access to it, so I get the same result as in Example 1.</p>
  <pre class="lang-sh prettyprint-override"><code>sudo apt install python3-wheel
  python3.8 -m venv test_env
  source test_env/bin/activate
  pip install markuppy
  </code></pre>
  <p>Output:</p>
  <pre><code>Collecting markuppy
    Downloading MarkupPy-1.14.tar.gz (6.8 kB)
  Building wheels for collected packages: markuppy
    Building wheel for markuppy (setup.py) ... error
    ERROR: Command errored out with exit status 1:
     command: /home/k/test_env/bin/python3 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '&quot;'&quot;'/tmp/pip-install-5xkssq1l/markuppy/setup.py'&quot;'&quot;'; __file__='&quot;'&quot;'/tmp/pip-install-5xkssq1l/markuppy/setup.py'&quot;'&quot;';f=getattr(tokenize, '&quot;'&quot;'open'&quot;'&quot;', open)(__file__);code=f.read().replace('&quot;'&quot;'\r\n'&quot;'&quot;', '&quot;'&quot;'\n'&quot;'&quot;');f.close();exec(compile(code, __file__, '&quot;'&quot;'exec'&quot;'&quot;'))' bdist_wheel -d /tmp/pip-wheel-aunof5xf
         cwd: /tmp/pip-install-5xkssq1l/markuppy/
    Complete output (6 lines):
    usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
       or: setup.py --help [cmd1 cmd2 ...]
       or: setup.py --help-commands
       or: setup.py cmd --help
    
    error: invalid command 'bdist_wheel'
    ----------------------------------------
    ERROR: Failed building wheel for markuppy
    Running setup.py clean for markuppy
  Failed to build markuppy
  Installing collected packages: markuppy
      Running setup.py install for markuppy ... done
  Successfully installed markuppy-1.14
  </code></pre>
  <h2>Example 5: Installing <code>wheel</code> at the system level and granting venv access to system site packages works</h2>
  <p>If I install <code>wheel</code> at the system level, then grant my venv access to system site packages (note the flag on the venv command) when I create it, then this issue does not happen.</p>
  <pre class="lang-sh prettyprint-override"><code>sudo apt install python3-wheel
  python3.8 -m venv test_env --system-site-packages
  source test_env/bin/activate
  pip install markuppy
  </code></pre>
  <p>Output:</p>
  <pre><code>Collecting markuppy
    Downloading MarkupPy-1.14.tar.gz (6.8 kB)
  Building wheels for collected packages: markuppy
    Building wheel for markuppy (setup.py) ... done
    Created wheel for markuppy: filename=MarkupPy-1.14-py3-none-any.whl size=7414 sha256=cefe8d9f20cecaf72253cab1e18acbdcb6d30827d7a3fd5a74bbef4935bc2e44
    Stored in directory: /home/k/.cache/pip/wheels/95/13/60/31c9d5f4cd012e491aeac154ef8b0ec964916523623eb02f0b
  Successfully built markuppy
  Installing collected packages: markuppy
  Successfully installed markuppy-1.14
  </code></pre>
  <p>The obvious downside to this approach is that it breaks isolation between your project's venv and the python packages installed on the system itself.</p>
  <h2>Example 6: None of this happens in Python3.7</h2>
  <pre class="lang-sh prettyprint-override"><code>python3.7 -m venv test_env
  source test_env/bin/activate
  pip install -U pip
  pip install markuppy
  </code></pre>
  <p>Output:</p>
  <pre><code>Collecting markuppy
    Downloading MarkupPy-1.14.tar.gz (6.8 kB)
  Using legacy 'setup.py install' for markuppy, since package 'wheel' is not installed.
  Installing collected packages: markuppy
      Running setup.py install for markuppy ... done
  Successfully installed markuppy-1.14
  </code></pre>
  <p>Although it does provide a warning that pip used <code>setup.py install</code> in lieu of <code>wheel</code>.</p>
  <h1>The Question</h1>
  <p>How are we supposed to deal with this <code>wheel</code> package? It seems that it's expected that we all have this package installed in most (all?) environments, but the environment tooling in the standard library does not automatically provide it.</p>
  <p>I like the idea of keeping my project environments completely isolated from the system python environment, so it looks like the only options that I can see are:</p>
  <ol>
  <li>Manually install the <code>wheel</code> package immediately after creating a new venv.</li>
  <li>Using another tool besides venv to manage environments.</li>
  </ol>