在适用于 Linux 的 Windows 子系统中创建 virtualenv 将创建一个旨在在 Linux 上而不是在 Windows 上运行的 virtualenv。这就是为什么在 WSL 上由 virtualenv 创建的文件无法被 Windows 识别(并且在 Powershell 上由 virtualenv 创建的文件将无法在 WSL 中使用)。
至于为什么 Windows virtualenv 中的文件要大得多,这是因为它们更多的是编译后的二进制和库文件,而不是脚本。
我的双启动机器上有两个 virtualenv,因此我们可以查看它们以进行等效比较。 (一个是 Python 3.6,一个是 Python3.7,但这不是太重要。)
以下是 Windows virtualenv 的文件:
2315 activate*
1067 activate.bat*
1755 activate.ps1*
1517 ativate_this.py*
1159 activate.xsh*
603 deactivate.bat*
102783 easy_install-3.7.exe*
102783 easy_install.exe*
103281 f2py.exe*
102765 pip3.7.exe*
102765 pip3.exe*
102765 pip.exe*
3748368 python37.dll*
58896 python3.dll*
99856 python.exe*
98320 pythonw.exe*
102761 wheel.exe*
这里是 Linux virtualenv 的文件:
2219 activate
1438 activate.csh
3103 activate.fish
1751 activate.ps1
1517 activate_this.py
1160 activate.xsh
259 easy_install*
259 easy_install-3.6*
242 f2py*
242 f2py3*
242 f2py3.6*
150 get_env_details*
246 pip*
246 pip3*
246 pip3.6*
72 postactivate
74 postdeactivate
69 preactivate*
75 predeactivate
7 python -> python3*
4526456 python3*
7 python3.6 -> python3*
2348 python-config*
237 wheel*
正如您所注意到的,Linux virtualenv 的文件比 Windows 的要小得多。这是正常的,不是问题。
原因是 Linux virtualenvs 中更多的文件是脚本,而不是二进制文件。脚本是包含将由解释器运行的代码的文件,而二进制文件是编译后的代码,可以直接运行(如 .exe 文件)或用作库(如 .dll 文件)。
在 Windows 虚拟环境中,activate、activate.bat、activate.ps1。 activate_this.py、activate.xsh 和 deactivate.bat 是脚本。您可以看到它们的大小范围从 0.6 到 2.3 kB,相当小。另一方面,easy_install-3.7.exe、easy_install.exe、f2py.exe、pip3.7.exe、pip3.exe、pip.exe、python.exe、pythonw.exe、wheel.exe 都是二进制可执行文件。您可以看到它们的范围从 98 到 103 kB,比脚本大得多。 python37.dll和python3.dll是库文件,也是编译后的二进制文件,但不能直接执行,而且体积也很大。 python3.dll 比 python37.dll 小很多,所以 python3.dll 可能只是引用了 python37.dll,但即便如此,python3.dll 与脚本相比仍然很大。
另一方面,在 Linux virtualenv 上,所有文件都是脚本,除了 python、python3 和 python3.6。 python3 是二进制可执行文件,python 和 python3.6 只是到 python3 的符号链接。
脚本通常较小的原因是因为它们运行的代码实际上在解释器中,而没有在文件本身中包含该代码。以pip为例。
这里是 Linux virtualenv 上文件 pip 的内容:
#!/home/nog642/.virtualenvs/virtualenv-name/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal.main import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())
这是一个 python 脚本,它在 virtualenv 的 python 解释器中运行。它导入 pip 模块,该模块包含在 virtualenv 结构的其他位置,然后在对命令行参数进行一些解析后运行 main 方法。
pip 的实际代码在其他地方,实际运行的可执行文件是 python3,然后它在解释器中运行此脚本。这就是文件最终只有 246 个字节的原因。
另一方面,Windows virtualenv 中的pip.exe 是 102,765 字节。这是因为它本身是一个可执行的二进制文件,而不是一个脚本。它包含它需要运行的所有代码,这些代码已经被编译。由于它是自包含的,并且不依赖文件结构中其他地方的代码,因此它最终会变得更大。