在 PYTHONPATH 到底应该设置什么?

我正在为一个 python 项目的其他开发人员撰写一份安装文档,并且一直在阅读 PYTHONPATH环境变量。我正在查看我当前的开发系统,并认为我有一些设置错误导致我的 IDE (IntelliJ)在查找 Python 库时行为不正确。

我已经看过了 给你给你的文档,但是我仍然不确定在 PYTHONPATH的环境变量中应该包含什么。

我将 PYTHONHOME指向“ C: Python 27”。

我当前的 PYTHONPATH设置为 PYTHONHOME。我还应该添加 sys.path的目录吗?

更新:

基于以下信息,不需要设置 PYTHONPATH,除非您希望 python 能够在默认情况下找到非标准库。例如,当我从安装程序安装 WxPython时,它会将它的库添加到 PYTHONPATH。我确实将 abc2设置为 python 安装的根目录,这样我就可以将它添加到我的系统 abc3环境变量中,这样我就可以在任何地方运行 python。

209599 次浏览

You don't have to set either of them. PYTHONPATH can be set to point to additional directories with private libraries in them. PYTHONHOME sets the location of default libraries.

Documentation:

PYTHONHOME
Change the location of the standard Python libraries. By default, the libraries are searched in prefix/lib/pythonversion and exec_prefix/lib/pythonversion, where prefix and exec_prefix are installation-dependent directories, both defaulting to /usr/local.

When PYTHONHOME is set to a single directory, its value replaces both prefix and exec_prefix. To specify different values for these, set PYTHONHOME to prefix:exec_prefix.

PYTHONPATH
Augment the default search path for module files. The format is the same as the shell’s PATH: one or more directory pathnames separated by os.pathsep (e.g. colons on Unix or semicolons on Windows). Non-existent directories are silently ignored.

In addition to normal directories, individual PYTHONPATH entries may refer to zipfiles containing pure Python modules (in either source or compiled form). Extension modules cannot be imported from zipfiles.

The default search path is installation dependent, but generally begins with prefix/lib/pythonversion (see PYTHONHOME above). It is always appended to PYTHONPATH.

An additional directory will be inserted in the search path in front of PYTHONPATH as described above under Interface options. The search path can be manipulated from within a Python program as the variable sys.path.

For most installations, you should not set these variables since they are not needed for Python to run. Python knows where to find its standard library.

The only reason to set PYTHONPATH is to maintain directories of custom Python libraries that you do not want to install in the global default location (i.e., the site-packages directory).

Make sure to read: http://docs.python.org/using/cmdline.html#environment-variables

Here is what I learned: PYTHONPATH is a directory to add to the Python import search path "sys.path", which is made up of current dir. CWD, PYTHONPATH, standard and shared library, and customer library. For example:

% python3 -c "import sys;print(sys.path)"
['',
'/home/username/Documents/DjangoTutorial/mySite',
'/usr/lib/python3.6', '/usr/lib/python3.6/lib-dynload',
'/usr/local/lib/python3.6/dist-packages', '/usr/lib/python3/dist-packages']

where the first path '' denotes the current dir., the 2nd path is via

%export PYTHONPATH=/home/username/Documents/DjangoTutorial/mySite

which can be added to ~/.bashrc to make it permanent, and the rest are Python standard and dynamic shared library plus third-party library such as django.

As said not to mess with PYTHONHOME, even setting it to '' or 'None' will cause python3 shell to stop working:

% export PYTHONHOME=''
% python3
Fatal Python error: Py_Initialize: Unable to get the locale encoding
ModuleNotFoundError: No module named 'encodings'


Current thread 0x00007f18a44ff740 (most recent call first):
Aborted (core dumped)

Note that if you start a Python script, the CWD will be the script's directory. For example:

username@bud:~/Documents/DjangoTutorial% python3 mySite/manage.py runserver
==== Printing sys.path ====
/home/username/Documents/DjangoTutorial/mySite # CWD is where manage.py resides
/usr/lib/python3.6
/usr/lib/python3.6/lib-dynload
/usr/local/lib/python3.6/dist-packages
/usr/lib/python3/dist-packages

You can also append a path to sys.path at run-time: Suppose you have a file Fibonacci.py in ~/Documents/Python directory:

username@bud:~/Documents/DjangoTutorial% python3
>>> sys.path.append("/home/username/Documents")
>>> print(sys.path)
['', '/usr/lib/python3.6', '/usr/lib/python3.6/lib-dynload',
'/usr/local/lib/python3.6/dist-packages', '/usr/lib/python3/dist-packages',
'/home/username/Documents']
>>> from Python import Fibonacci as fibo

or via

% PYTHONPATH=/home/username/Documents:$PYTHONPATH
% python3
>>> print(sys.path)
['',
'/home/username/Documents', '/home/username/Documents/DjangoTutorial/mySite',
'/usr/lib/python3.6', '/usr/lib/python3.6/lib-dynload',
'/usr/local/lib/python3.6/dist-packages', '/usr/lib/python3/dist-packages']
>>> from Python import Fibonacci as fibo

A little bit less 'ad hoc' solution than directly manipulating the PYTHONPATH exists with the use of the flag -e with the pip command, and allows to seamlessly install local libraries that can be imported, and re-imported to reflect changes made.

In order to be able to import mypackage the same way you do with any other module, the correct approach is to use pip locally:

python -m pip install -e /path_to_package/mypackage/

  • python -m ensures you are using the pip package from the same python installation you are currently using.

  • -e makes it editable, i/e import mypackage will reload after you make some changes, instead of using the cached one.

mypackage must be an installable package, i/e contain an __init__.py file, and a basic setup.py (or pyproject.toml file for pipenv)

minimal setup.py

from setuptools import find_packages, setup


setup(
name='mypackage',          # Required
version='0.0.1',           # Required
packages=find_packages(),  # Required
)

the package structure must be like this:

mypackage/
setup.py
mypackage/    <----- this is a folder inside the other `mypackage/` folder
__init__.py

or as a tree:

└── python_perso                folder
└── mypackage                   folder
├── mypackage                   folder
│   └── __init__.py
└── setup.py

[edit] after installation, the directory will look like this:
(for a package named mypackage)

└── python_perso
└── mypackage
├── mypackage
│   ├── __init__.py
│   └── __pycache__
│       └── __init__.cpython-38.pyc
├── mypackage.egg-info
│   ├── PKG-INFO
│   ├── SOURCES.txt
│   ├── dependency_links.txt
│   └── top_level.txt
└── setup.py


5 directories, 7 files