安装 Python 包

你的 Python 包都装到哪了?

假设当前 Python 解释器的路径是 $path_prefix/bin/python,那么你启动 Python 交互环境或者用这个解释器运行脚本时,会默认寻找以下位置

  1. $path_prefix/lib(标准库路径)
  2. $path_prefix/lib/pythonX.Y/site-packages(三方库路径,X.Y 是对应 Python 的主次版本号,如 3.7, 2.6)
  3. 当前工作目录(pwd命令的返回结果)

几个有用的函数

  • sys.executable:当前使用的 Python 解释器路径
  • sys.path:当前包的搜索路径列表
  • sys.prefix:当前使用的 $path_prefix
  • 除此之外,还在以在命令行中运行 python -m site,会打印出当前 Python 的一些信息,包括搜索路径列表。

使用环境变量添加搜索路径

如果你的包的路径不存在上面列出的搜索路径列表里,可以把路径加到 PYTHONPATH 环境变量里

虚拟环境

虚拟环境就是为了隔离不同项目的依赖包,使他们安装到不同的路径下,以防止依赖冲突的问题。理解了 Python 是如何安装包的机制之后就不难理解虚拟环境(virtualenv, venv模块)的原理。其实,运行virtualenv myenv会复制一个新的 Python 解释器到myenv/bin下,并创建好myenv/libmyenv/lib/pythonX.Y/site-packages等目录(venv模块不是用的复制,但结果基本一样)。执行source myenv/bin/activate以后会把myenv/bin塞到PATH前面,让这个复制出来的 Python 解释器最优先被搜索到。这样,后续安装包时,$path_prefix就会是myenv了,从而实现了安装路径的隔离。

运行 Python 脚本

运行一个子目录中某脚本的代码,应该用 python -m <module_name>python -m 后面的参数是(以 . 分隔的)模块名,而不是路径名。

pip

运行 pip 有两种方式:

  • pip ...
  • python -m pip ...

第一种方式和第二种方式大同小异,区别是第一种方式使用的 Python 解释器是写在 pip 文件的 shebang 里的,一般情况下,如果你的 pip 路径是 $path_prefix/bin/pip,那么 Python 路径对应的就是 $path_prefix/bin/python。如果你用的是 Unix 系统则 cat $(which pip) 第一行就包含了 Python 解释器的路径。第二种方式则显式地指定了 Python 的位置。

# update
pip install --upgrade pip

# install package
pip install numpy
pip install -U numpy # --upgrade
pip --proxy=hostname:port install requests

# install to target dir
pip install beautifulsoup4 -t ./

# check packages
pip list

# check version
pip freeze | grep [package_name]

使用国内源

pip install -i https://pypi.mirrors.ustc.edu.cn/simple package
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple package
pip install -i http://pypi.douban.com/simple package
pip install -i http://mirrors.aliyun.com/pypi/simple package
pip install -i https://mirrors.cloud.tencent.com/pypi/simple package

指定版本

pip install pyspark==2.3.2

指定平台

pip download package --platform linux_x86_64 --only-binary=:all: --python-version 27
pip download package --platform macosx-10_10_x86_64 --only-binary=:all: --python-version 27
pip download pyspark --platform win_amd64 --only-binary=:all: --python-version 27

pipx

install and run Python command-line applications without causing dependency conflicts with other packages installed on the system

Docs

Install:

# macOS
brew install pipx
pipx ensurepath

# Ubuntu
sudo apt update
sudo apt install pipx
pipx ensurepath

venv/virtualenv

venv is Included in the Python standard library as of Python 3.3

# create virtual env
python3 -m venv <DIR>

# activate
source <DIR>/bin/activate

# deactivate
deactivate

virtualenv is a third-party library, can create virtual environments for other versions of Python

Install:

pip install virtualenv

Usage:

python3 -m virtualenv <DIR>
source <DIR>/bin/activate
deactivate

conda/miniforge

free alternative: miniforge3

mamba env list

Usage:

# cheak version
conda -V

# update
conda update conda

# list env
conda env list

# create new env
conda create --name myenv python=3.5

# activate env
source activate myenv

# install package
# use pip or conda, do not use them simultaneously
pip install numpy
conda install numpy

# unistall
conda unistall numpy
conda remove --name myenv numpy

# check packages
conda list

# deactivate env
source deactivate myenv

# remove env
conda env remove --name myenv

国内镜像源

中科大镜像源

# 添加清华镜像源
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge 
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/msys2/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/

# 恢复默认设置
conda config --remove-key channels

问题

zsh 中无法识别方括号

原因:zsh treating [] as special characters

解决方法:disable zsh globbing by add noglob

noglob pip install --upgrade diffusers[torch]

在脚本中调用

# 方法一
source /YOUR_CONDA_PATH/bin/activate ${conda_env}

# 方法二
conda run -n ${conda_env} echo hello

iPython

Run command

!<command>

Change directory

%cd

Reset

%reset

Run python file

%run <filename>
%paste  # run code in clipboard

Variable information

<variable>?

display variables

%who, %whos 

previous output

_(one underscore)
__(two underscore)

Logging

%logstart, %logstop, %logon, %logoff

Print input history

%hist

Bookmark

Add bookmark

%bookmark <name> [dir name]

List all bookmarks

%bookmark -l

Jupyter Notebook

Github - jupyterlab

安装

# jupyter notebook
pip install notebook

# jupyter lab
pip install jupyterlab

配置远程登录

命令行方式

jupyter lab --ip 0.0.0.0 --port 8888

配置方式

  1. 设置密码
from IPython.lib import passwd
passwd()

将上面的密码哈希值复制出来

  1. 生成配置文件jupyter notebook --generate-config

  2. 修改配置文件vi ~/.jupyter/jupyter_notebook_config.py

c.NotebookApp.allow_remote_access = True
c.NotebookApp.open_browser = False
c.NotebookApp.ip = '*'    # 所有IP都能访问
c.NotebookApp.password = 'sha1:1058604ee835:4fb758cac6ee47f2ff8d80c1735e219f26e34d98'    # 复制上边密码
c.NotebookApp.port = 8888    # 端口
c.NotebookApp.notebook_dir = '~/Jupyter'

配置Nginx转发

修改juputer配置文件vi ~/.jupyter/jupyter_notebook_config.py

c.NotebookApp.base_url = '/jupyter'

修改nginx配置

server {
    listen       443 ssl;
    server_name  devcloud;
    client_max_body_size 10G;

    location /jupyter {
        proxy_pass http://127.0.0.1:8888;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_redirect off;
    }
}

Add conda environment to kernel

conda activate <env>
conda install -y -c anaconda ipykernel
python -m ipykernel install --user --name=<env>

Packaging

Docs

Steps

  1. 准备项目结构:
    1. 创建一个项目文件夹,如packaging_tutorial
    2. 在项目文件夹内创建源代码文件夹src
    3. src文件夹内创建你的包文件夹,如example_package_YOUR_USERNAME_HERE
    4. 在包文件夹内创建__init__.py和示例模块文件example.py
packaging_tutorial/
├── LICENSE
├── pyproject.toml
├── README.md
├── src/
│   └── example_package_YOUR_USERNAME_HERE/
│       ├── __init__.py
│       └── example.py
└── tests/
  1. 修改 pyproject.toml 配置元数据、LICENSE 文件、README.md 文件
[project]
name = "example_package_YOUR_USERNAME_HERE"
version = "0.0.1"
authors = [
  { name="Example Author", email="author@example.com" },
]
description = "A small example package"
readme = "README.md"
requires-python = ">=3.8"
classifiers = [
    "Programming Language :: Python :: 3",
    "License :: OSI Approved :: MIT License",
    "Operating System :: OS Independent",
]

[project.urls]
Homepage = "https://github.com/pypa/sampleproject"
Issues = "https://github.com/pypa/sampleproject/issues"

# 构建后端,默认为 Hatchling
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
  1. 打包,会在dist目录下生成.whl.tar.gz文件。
# 安装打包工具
python3 -m pip install --upgrade build

# 打包
python3 -m build

传统项目也使用写 setup.py 文件,然后通过 python setup.py sdist bdist_wheel 命令打包,因为长期以来 Setuptools 是 Python 项目打包的事实标准。使用 build 来打包是更现代的方式。

  1. 注册账号:TestPyPI,获取 Token,用于后续的上传
  2. 上传
# 安装上传 PyPI 的工具 twine
python3 -m pip install --upgrade twine

# 上传
python3 -m twine upload --repository testpypi dist/*
  1. 验证
# Install 
# python3 -m pip install --index-url https://test.pypi.org/simple/ --no-deps example-package-YOUR-USERNAME-HERE

from example_package_YOUR_USERNAME_HERE import example
example.add_one(2)
  1. 上传到正式的 PyPI