Skip to content

Python

8 posts with the tag “Python”

Python-slim镜像制作

Python基础镜像制作,添加中文字体

Windows 电脑上,可以在 C:\Windows\Fonts 下找到。 或者下载开源且风格类似的 思源宋体 (Noto Serif CJK SC)STIX (用于数学公式)

FROM python:3.11-slim
# 使用国内镜像源
# 防止 hidden 的 bookworm 源干扰
RUN rm -rf /etc/apt/sources.list.d/* /etc/apt/sources.list
RUN echo "deb http://mirrors.aliyun.com/debian/ testing main non-free non-free-firmware contrib" > /etc/apt/sources.list && \
echo "deb-src http://mirrors.aliyun.com/debian/ testing main non-free non-free-firmware contrib" >> /etc/apt/sources.list && \
echo "deb http://mirrors.aliyun.com/debian-security/ testing-security main non-free non-free-firmware contrib" >> /etc/apt/sources.list
# 1. 更新源并安装 fontconfig
# --no-install-recommends: 避免安装不必要的推荐包,保持镜像小
# rm -rf /var/lib/apt/lists/*: 安装后删除 apt 缓存,减小镜像体积 (Slim 镜像的最佳实践)
RUN apt-get update && \
apt-get install -y --no-install-recommends fontconfig && \
rm -rf /var/lib/apt/lists/*
# 2. 创建字体目录
RUN mkdir -p /usr/share/fonts/truetype/custom
# 3. 拷贝字体文件 (确保你的项目目录下有 fonts/simsun.ttc)
COPY ./fonts/simsun.ttc /usr/share/fonts/truetype/custom/
# 4. 刷新系统字体缓存 (现在这个命令可以成功运行了)
RUN fc-cache -fv
# --- 关键修改结束 ---
# 下面是原本的构建步骤
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
# ... CMD 等指令
  1. apt-get install fontconfig:

    • python:3.11 (完整版) 基于 Debian 完整版,通常自带很多工具。
    • python:3.11-slim 基于 Debian Slim,砍掉了非必要的工具(包括管理字体的工具)。如果不手动安装 fontconfig,你就无法将新字体注册到系统里。
  2. rm -rf /var/lib/apt/lists/*:

    • slim 镜像中,安装完软件后如果不清理缓存,会白白增加这一层的体积。这是编写高质量 Dockerfile 的标准操作。
  • 拷贝指令 (COPY):本身没有影响,完全通用。
  • 刷新指令 (fc-cache):在 slim 镜像下必须先安装 fontconfig 才能用。

Python: Annotated和Pydantic

typing.Annotated 在 Python3.9 版中引入,用于为类型注解添加元数据。作为 PEP 593 -- Flexible function and variable annotations 的一部分被添加到 typing 模块中。使用 AnnotatedPython 环境必须是 3.9 或更高版本。 typing.Annotated 的核心作用是为现有的 Python 类型添加元数据(metadata)。它本身并不执行任何运行时的类型检查或验证。可以将 Annotated 看作是一个类型装饰器,它允许你将额外的信息(可以是任何 Python 对象) 与一个类型关联起来。

这个设计的主要目的是为了让第三方工具能够更好地理解类型注解,从而提供更丰富的功能,例如类型检查、文档生成等,且无需修改 Python 的核心类型系统。通过使用 Annotated,开发者可以更灵活地表达类型信息,使代码更加清晰和可维护,

Pydantic 是一个 Python 库,主要用于数据验证和解析。它通过 Python 的类型提示 (type hints) 来定义数据的结构,并在运行时验证数据的有效性。

以下是 Pydantic 的主要用途和优点:

  • 数据验证 (Data Validation): 这是 Pydantic 最核心的功能。你可以使用 Pydantic 模型清晰地定义预期的数据结构和类型。当接收到外部数据(例如,来自 API 请求、配置文件、用户输入等)时,Pydantic 会自动根据你定义的模型进行验证。如果数据不符合预期类型或约束,Pydantic 会抛出详细的错误信息,告诉你哪些字段出了问题以及具体原因。
  • 数据解析 (Data Parsing): 除了验证,Pydantic 还能将输入数据解析成 Python 对象。即使输入数据是字符串、数字或其他格式,Pydantic 也会尝试将其转换为模型中定义的 Python 类型。例如,一个字符串 “123” 可以被解析成 int 类型。
  • 数据序列化 (Data Serialization): Pydantic 模型可以将 Python 对象序列化为其他格式,如 JSON。这对于构建 API 接口非常有用,因为你需要将 Python 对象转换为 JSON 格式发送给客户端。
  • 类型提示的强大利用: Pydantic 充分利用了 Python 3.6+ 引入的类型提示。通过类型提示,你可以清晰地表达数据的预期结构,这不仅方便了 Pydantic 的验证和解析,也提高了代码的可读性和可维护性,并能与 MyPy 等静态类型检查工具良好集成。
  • JSON Schema 生成: Pydantic 可以根据你的模型自动生成 JSON Schema。JSON Schema 是一种描述 JSON 数据结构的标准化方式,这对于 API 文档生成和与其他系统进行数据交互非常有用。
  • 与 Web 框架集成: Pydantic 与许多流行的 Python Web 框架(如 FastAPI、Starlette)无缝集成。FastAPI 甚至在底层 heavily rely on Pydantic 来处理请求和响应的数据验证和序列化。
  • 自定义验证器 (Custom Validators): 除了基本的类型验证,Pydantic 还允许你定义自定义的验证逻辑,以满足更复杂的业务规则。你可以编写函数来检查字段的值是否符合特定的要求。
  • 数据清洗和转换 (Data Cleaning and Transformation): 在验证过程中,Pydantic 还可以对数据进行清洗和转换。例如,你可以定义将字符串自动去除首尾空格,或者将日期字符串转换为 datetime 对象。

总而言之,Pydantic 主要用于确保你的 Python 应用程序接收和处理的数据是有效和符合预期的。它可以帮助你减少因数据格式错误而引发的 bug,提高代码的健壮性和可靠性,并简化数据处理相关的开发工作。

一些常见的应用场景包括:

  • API 开发: 验证和解析 API 请求的输入数据,以及序列化 API 的输出数据。
  • 数据处理管道: 确保从不同来源读取的数据符合预期的格式和类型。
  • 配置文件解析: 加载和验证应用程序的配置文件。
  • 用户输入验证: 验证 Web 表单或命令行工具接收到的用户输入。
  • 机器学习模型的数据预处理: 确保输入模型的数据具有正确的结构和类型。
  • typing.Annotated: 是 Python 类型提示系统的一部分,提供了一种为现有类型添加元数据的标准方法。它本身不执行任何运行时操作,而是让第三方工具能够读取和利用这些额外的元数据。
  • Pydantic: 专注于数据建模、验证、解析和序列化,通过定义 Pydantic 模型并利用类型提示来实现这些功能。它是一个功能强大的库,用于处理外部数据并确保其符合预期的结构和类型。

在实际应用中,Annotated 经常和 Pydantic 组合使用,以增强 Pydantic 模型的功能。虽然 Pydantic 也可以单独使用,但结合 Annotated 可以提供更灵活和标准化的方式来定义模型的行为。

基本的数据验证和解析: 当你只需要定义数据的基本结构和类型,并进行简单的验证和解析时,可以直接使用 Pydantic 模型。例如:

from pydantic import BaseModel
class User(BaseModel):
id: int
name: str
signup_ts: float | None = None

在这种情况下,Pydantic 会根据类型提示自动进行类型检查和基本的数据转换。

函数参数和返回值注释 (使用 Field):

from pydantic import Field
def search_database(
query: str = Field(description="Search query string"),
limit: int = Field(10, description="Maximum number of results", ge=1, le=100)
) -> list:
...

与这种方式相比,如果只需要需要定义简单的数据结构,并且不需要复杂的验证或序列化,可以直接使用 Python 的类型提示:

def search_database(
query: str,
limit: int,
) -> list:
...
  • 优点:
    • 结构化数据: Field 来自 pydantic 或类似的库,它允许你定义更丰富的数据类型信息,例如描述、默认值、验证规则(ge, le)。
    • 自动化文档和验证: 这些信息可以被用于自动生成 API 文档(例如使用 FastAPI),以及在运行时进行数据验证。
    • IDE 支持: 现代 IDE 可以利用这些信息提供更好的代码提示和错误检查。
  • 缺点:
    • 依赖外部库: 你需要引入 pydantic 或类似的库。
    • 更冗长: 代码量相对较多,对于简单的类型注释可能显得过于繁琐。
from typing import Annotated
from pydantic import Field
def analyze_metrics(
# number with range constraints
count: Annotated[int, Field(description="数据数量", ge=1, le=100)],
ratio: Annotated[float, Field(description="比率", ge=0, le=1)],
# String with pattern and length constraints
user_id: Annotated[
str, Field(description="用户ID 格式: XX0000", pattern=r"^[a-z]{2}\d{4}$")
],
comment: Annotated[str, Field(description="备注", min_len=3, max_length=500)] = "",
factor: Annotated[float, Field(description="因子", multiple_of=5)] = 10,
) -> dict[str, float]:
"""分析一组数据的统计信息."""
pass
  • 优点:
    • 类型提示和元数据: 使用 Annotated 可以将类型提示与元数据(例如 Field)结合起来。
    • 灵活性: 允许你添加多个元数据,不仅限于描述和验证规则。
    • 标准化: Annotated 是 Python 3.9 引入的标准库 typing 的一部分,因此不需要额外的依赖(除非 Field 来自外部库)。
  • 缺点:
    • 可读性略差: 相对于简单的类型提示,Annotated 的语法可能稍微复杂一些。
    • 需要 Python 3.9+: Annotated 是 Python 3.9 引入的特性。

Annotated 通常与 Pydantic 结合使用,以增强 Pydantic 模型字段的定义,添加自定义验证逻辑、元数据等。

  • 基本数据建模: 如果你只需要定义简单的数据结构,并且不需要复杂的验证或序列化,可以直接使用 Python 的类型提示。
  • 数据验证和解析: 如果你需要对输入数据进行严格的验证和解析,并将其转换为 Python 对象,选择 Pydantic。
  • 自定义验证和元数据: 如果你需要在 Pydantic 模型中添加自定义的验证逻辑或额外的元数据(例如字段描述、别名、格式等),那么使用 Annotated 结合 Pydantic 是推荐的做法。
  • 第三方库集成: 如果你使用的第三方库支持 Annotated,并且你想利用类型提示中的元数据来配置这些库的行为,那么可以使用 Annotated。例如,Pydantic 利用 Annotated 来支持自定义验证器 (PlainValidator) 和字段配置 (Field).

NeoVim调试Python、Golang

在上两篇中NeoVim开发环境配置NeoVim配置Go开发环境(进阶), 完成了将NeoVim作为IDE最基本常用功能的,这里将进一步完成对Python、Golang调试环境的配置。

在NeoVim上进行调试(Python、Golang)有nvim-dapvimspector可做选择,这里 将使用vimspector进行调试工作。

在plug.vim中添加:

Plug 'puremourning/vimspector'

:PlugInstall安装插件。 在init.vim中,添加:

let g:vimspector_enable_mappings='HUMAN'

将vimspector 快捷键映射配置为HUMAN模式:

KeyMappingFunction
F5<Plug>VimspectorContinueWhen debugging, continue. Otherwise start debugging.
F3<Plug>VimspectorStopStop debugging.
F4<Plug>VimspectorRestartRestart debugging with the same configuration.
F6<Plug>VimspectorPausePause debuggee.
F9<Plug>VimspectorToggleBreakpointToggle line breakpoint on the current line.
<leader>F9<Plug>VimspectorToggleConditionalBreakpointToggle conditional line breakpoint or logpoint on the current line.
F8<Plug>VimspectorAddFunctionBreakpointAdd a function breakpoint for the expression under cursor
<leader>F8<Plug>VimspectorRunToCursorRun to Cursor
F10<Plug>VimspectorStepOverStep Over
F11<Plug>VimspectorStepIntoStep Into
F12<Plug>VimspectorStepOutStep out of current function scope

下面是各个语言调试使用的Adapter:

通过:VimspectorInstall debugpy:VimspectorInstall delve 完成对python、go 调试adapter的安装。

由于NeoVim的LSP指定当前根目录是各LSP Server提供的功能,在调试Ptyon时,在目录中添加.pyrightconfig.json文件:

{
"executionEnvironments": [
{"root": "."}
]
}

如上配置,将.pyrightconfig.json文件所在目录,作为Root目录。

配置调试器,添加配置文件 .vimspector.json:

{
"configurations": {
"run": {
"adapter": "debugpy",
"default": true,
"configuration": {
"request": "launch",
"type": "python",
"cwd": "${workspaceRoot}",
"stopOnEntry": true,
"program": "${file}"
},
"breakpoints": {
"exception": {
"raised": "N",
"uncaught": "",
"userUnhandled": ""
}
}
}
}
}

configuration.program指定要调试的程序,可以通过configuration.env配置调试时程序的环境变量,configuration.args配置参数。 如在调试一个scrapy的爬虫程序时,通过program指定scrapy位置,args指定启动的具体spider:

{
"configurations": {
"run": {
"adapter": "debugpy",
"default": true,
"configuration": {
"request": "launch",
"type": "python",
"program": "~/opt/miniconda3/envs/p3/bin/scrapy",
"cwd": "${workspaceRoot}",
"stopOnEntry": true,
"args": ["crawl", "${fileBasenameNoExtension}"]
},
"breakpoints": {
"exception": {
"raised": "N",
"uncaught": "",
"userUnhandled": ""
}
}
}
}
}

配置调试器,添加配置文件 .vimspector.json,如:

{
"configurations": {
"default": {
"adapter": "delve",
"default": true,
"configuration": {
"request": "launch",
"mode": "debug",
"cwd": "${workspaceRoot}",
"stopOnEntry": true,
"program": "${file}",
"args": [
"-http_addr","localhost:8084"
]
},
"breakpoints": {
"exception": {
"raised": "N",
"uncaught": "",
"userUnhandled": ""
}
}
}
}
}

指定adapter为delve来调试go程序,program指定要调试的程序文件,args指定参数http_addr=localhost:8084

  1. vimspector
  2. Debugging python in neovim
  3. Neovim — Debugging Application
  4. Programming Go in Neovim
  5. nvim-lsconfig Configurations
  6. vim-delve
  7. golang: debugging application in neovim
  8. nvim-dap
  9. debug-adapter-configuration

Python爬虫

Conda 下载安装包进行安装, 使用conda管理Python环境 进行Python环境配置管理。

1.1 Beautiful Soup

Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式.Beautiful Soup会帮你节省数小时甚至数天的工作时间.

安装Beautiful Soup

Terminal window
$ conda install beautifulsoup4
#安装解析器lxml
$ conda install lxml
  1. conda install 遇到 “Collecting package metadata (current_repodata.json): failed”
Terminal window
$ conda install lxml (p3) 0 [15:43:43]
Collecting package metadata (current_repodata.json): failed
CondaHTTPError: HTTP 000 CONNECTION FAILED for url <https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/osx-64/current_repodata.json>
Elapsed: -
An HTTP error occurred when trying to retrieve this URL.
HTTP errors are often intermittent, and a simple retry will get you on your way.
'https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/osx-64'

关闭conda的ssl验证即可:

Terminal window
$ conda config --set ssl_verify false
  1. https://conda.io/en/latest/miniconda.html
  2. Beautiful Soup 4.4.0 文档

Pyton生成标定板

做一个和Opencv相关的项目调研,这里留下些记录….

使用Opencv进行图摄像头标定时,要用到标定板。下面用Python开始生成一个标定板:

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""
Created on Wed Mar 21 16:21:49 2018
@author: xiaoxiwang
"""
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 宽450像素
width = 450
# 高350像素
height = 350
# 50 x 50 一个单元格
length = 50
img = np.zeros((width, height), dtype=np.uint8)
for j in range(height):
for i in range(width):
if ((int)(i / length) + (int)(j / length)) % 2:
img[i, j] = 255
# 将标定板保存为图checkboard.jpg
cv2.imwrite('checkerborad.jpg', img)
# 使用matplotlib查看生成的标定板
plt.subplot(111), plt.imshow(img, cmap='gray'), plt.title('Output')
plt.show()

conda管理Python环境

近期做一个项目的调研,需要使用到OpenCV、Python,这里记录anaconda进行Python环境配置管理过程。

  • virtualenv,用于在一台机器上创建多个独立的Python虚拟运行环境,多个Python环境相互独立,互不影响
  • pyenv, Python版本管理工具,可以方便的在多个Python版本之间进行切换
  • Anaconda,Anaconda是一个用于科学计算的Python发行版,支持 Linux, Mac, Windows系统,提供了包管理与环境管理的功能,可以很方便地解决多版本python并存、切换以及各种第三方包安装问题。Anaconda利用工具/命令conda来进行package和environment的管理,并且已经包含了Python和相关的配套工具。

conda可以理解为一个工具,也是一个可执行命令,其核心功能是包管理与环境管理。包管理与pip的使用类似,环境管理则允许用户方便地安装不同版本的python并可以快速切换。Anaconda则是一个打包的集合,里面预装好了conda、某个版本的python、众多packages、科学计算工具等等,所以也称为Python的一种发行版

Anaconda下载安装参见官网下载,支持Windows,macOS,Linux平台。

Conda环境管理功能允许同时安装多个不同版本的Python,并可以自由切换。

# 查看已经安装的环境
conda info -e
# 创建一个名为python34的环境,指定Python版本是3.4(不用管是3.4.x,conda会为我们自动寻找3.4.x中的最新版本)
conda create --name python34 python=3.4
# 安装好后,使用activate激活某个环境
activate python34 # for Windows source activate python34 # for Linux & Mac
# 激活后,会发现terminal输入的地方多了python34的字样,实际上,此时系统做的事情就是把默认2.7环境从PATH中去除,再把3.4对应的命令加入PATH
python --version
# 可以得到`Python 3.4.5 :: Anaconda 4.1.1 (64-bit)`,即系统已经切换到了3.4的环境
# 如果想返回默认的python 2.7环境,运行
deactivate python34 # for Windows source deactivate python34 # for Linux & Mac
# 删除一个已有的环境
conda remove --name python34 --all
# 查看当前环境下已安装的包
conda list
# 查看某个指定环境的已安装包
conda list -n python34
# 查找package信息
conda search numpy
# 安装package
conda install -n python34 numpy
# 如果不用-n指定环境名称,则被安装在当前活跃环境
# 也可以通过-c指定通过某个channel安装
# 更新package
conda update -n python34 numpy
# 删除package
conda remove -n python34 numpy

由于默认的安装源在国外,conda下载速度十分缓慢。可以使用清华大学TUNA镜像。 TUNA 还提供了 Anaconda 仓库的镜像,运行以下命令:

conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
conda config --set show_channel_urls yes

即可添加 Anaconda Python 免费仓库。

该配置保存在.condarc文件,也可以直接进行配置,Windows为C://Users/username/.condarc,Linux/Mac为~/.condarc。

channels:
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
- defaults
ssl_verify: true
show_channel_urls: true
Terminal window
$ conda config --remove channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
Terminal window
$ conda config --show
add_anaconda_token: True
add_pip_as_python_dependency: True
aggressive_update_packages:
- ca-certificates
- certifi
- openssl
allow_conda_downgrades: False
allow_cycles: True
allow_non_channel_urls: False
allow_softlinks: False
always_copy: False
always_softlink: False
always_yes: None
anaconda_upload: None
....

Mac配置Selenium + Python3

Selenium也是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE、Mozilla Firefox、Mozilla Suite等。这个工具的主要功能包括:测试与浏览器的兼容性——测试你的应用程序看是否能够很好得工作在不同浏览器和操作系统之上。测试系统功能——创建衰退测试检验软件功能和用户需求。支持自动录制动作和自动生成。Net、Java、Perl等不同语言的测试脚本。Selenium 是ThoughtWorks专门为Web应用程序编写的一个验收测试工具。

Mac OS 10.13.2中自带的Python版本是2.7,可以使用Anaconda使用管理环境,并可以方便的切换到Python3。

pip install selenium

Selenium3.0后,Firefox浏览器同其他浏览器一样都已经独立出来,必须要使用下载和配置浏览器驱动,而且浏览器和驱动的版本必须匹配,否则会出现各种诡异的错误。

归功于某些不可抗拒因素,下载谷歌相关联的包不是那么方便,需要的驱动可以在淘宝镜像上下载。

下载到ChromeDriver后,并将驱动的所在路径加入环境变量中。

编写一个简单的测试脚本,进入www.taobao.com

from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://cart.taobao.com")

执行脚本后会打开一个新增chrome浏览器,并进入淘宝首页。

1. ChromeDriver和Chrome的版本对应关系:

Section titled “1. ChromeDriver和Chrome的版本对应关系:”
ChromeDriver版本Chrome版本
v2.35v62-64
v2.34v61-63
v2.33v60-62
v2.32v59-61
v2.31v58-60
v2.30v58-60
v2.29v56-58
v2.28v55-57
v2.27v54-56
v2.26v53-55
v2.25v53-55
v2.24v52-54
v2.23v51-53
v2.22v49-52
v2.21v46-50
v2.20v43-48

附:ChromeDriver可以在下面的链接下载到:

http://chromedriver.storage.googleapis.com/index.html
// OR
https://npm.taobao.org/mirrors/chromedriver/

2. 在mac上使用webdriver调用chrome浏览器发生错误:

Section titled “2. 在mac上使用webdriver调用chrome浏览器发生错误:”
raise WebDriverException("Can not connect to the Service %s" % self.path)
selenium.common.exceptions.WebDriverException: Message: Can not connect to the Service chromedriver

修改办法,将 127.0.0.1 localhost添加到/etc/hosts配置文件中, 在终端中输入

Terminal window
sudo killall -HUP mDNSResponder

使hosts文件的更改生效。

注:解决办法来自github.com/SeleniumHQ

(Mac)PIP使用国内镜像

PIP使用国外源安装软件包,下载速度非常慢,将PIP安装源头替换为国内镜像,可以大幅提高下载速度,提高安装成功率。

  1. 清华:https://pypi.tuna.tsinghua.edu.cn/simple
  2. 阿里云:http://mirrors.aliyun.com/pypi/simple/
  3. 中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/
  4. 华中科技大学:http://pypi.hustunique.com/
  5. 山东理工大学:http://pypi.sdutlinux.org/
  6. 豆瓣:http://pypi.douban.com/simple/

使用指定的镜像源, 可以临时指定,也可以通过修改配置文件,始终生效。

可以在使用pip命令时,指定参数:-i

$ pip install myqr -i https://pypi.tuna.tsinghua.edu.cn/simple

pip将会从清华的镜像中下载安装软件包myqr。

在不同系统中,配置文件的路径不同。

  • Linux/Unix/Mac OS系统,默认配置文件路径为:
$HOME/.pip/pip.conf
  • Windows,默认配置文件路径为:
%HOME%/pip/pip.ini

注:如果默认路径下不存在配置文件,需要新建

如,使用阿里云镜像可以下面的配置:

[global]
index-url = http://mirrors.aliyun.com/pypi/simple/
[install]
trusted-host=mirrors.aliyun.com