书籍翻译技术知识点详解

书籍翻译项目 - 技术知识点详解

项目名称: PDF书籍自动翻译系统
作者: MrSponge
创建时间: 2026-05-05
版本: v1.0


目录

  1. Python 基础语法与特性
  2. 面向对象编程 (OOP)
  3. 模块与包管理
  4. 核心第三方库详解
  5. 项目架构与设计模式
  6. 文件操作与路径处理
  7. 日志记录系统
  8. 配置管理
  9. 命令行参数处理
  10. 异常处理
  11. 类型提示 (Type Hints)
  12. 文件编码与字符处理

1. Python 基础语法与特性

1.1 文件编码声明

# -*- coding: utf-8 -*-

知识点:

  • Python 2 需要显式声明文件编码,Python 3 默认使用 UTF-8
  • 放在文件第一行或第二行
  • 确保中文注释和字符串正常显示

1.2 多行字符串 (Docstrings)

"""
----------------------------------------
@Author  : MrSponge
@Time    : 2026-05-05 16:09:01
@Version : v1.0
@Description: TODO - 书籍翻译项目启动文件
----------------------------------------
"""

知识点:

  • 使用三个引号 """''' 创建多行字符串
  • 通常用于模块、类、函数的文档说明
  • 可以通过 __doc__ 属性访问

1.3 f-string 格式化字符串

log.info(f'开始翻译文件:{file_path}')
log.info(f'输出格式:{file_format}')

知识点:

  • Python 3.6+ 引入的格式化方式
  • 在字符串前加 fF
  • 使用 {} 包裹变量或表达式
  • 性能优于 %.format()

示例:

name = "Python"
version = 3.9
print(f'{name} {version}')  # 输出: Python 3.9
print(f'{name.upper()}')    # 输出: PYTHON

1.4 条件表达式 (三元运算符)

file_format = args.file_format if args.file_format else config['common'].get('file_format', 'PDF')

语法: 值1 if 条件 else 值2

等价于:

if args.file_format:
    file_format = args.file_format
else:
    file_format = config['common'].get('file_format', 'PDF')

1.5 链式比较

if page_index < len(self.book.pages) - 1:

知识点:

  • Python 支持 a < b < c 这样的链式比较
  • 等价于 a < b and b < c

1.6 列表推导式

cleaned_lines = [line.strip() for line in lines if line.strip()]

知识点:

  • 简洁的列表创建方式
  • 语法: [表达式 for 元素 in 可迭代对象 if 条件]
  • 比传统 for 循环更快

示例:

# 传统方式
squares = []
for x in range(10):
    squares.append(x**2)

# 列表推导式
squares = [x**2 for x in range(10)]

1.7 字符串方法

常用方法:

# 分割字符串
lines = raw_text.splitlines()  # 按行分割

# 去除空白字符
line.strip()        # 去除首尾空白
line.lstrip()       # 去除左侧空白
line.rstrip()       # 去除右侧空白

# 查找子串
subfix = path[path.rindex('.'):]  # 从右侧查找 '.' 的位置

# 替换字符串
raw_text = raw_text.replace(cell, '', 1)  # 替换第一次出现的内容

# 连接列表
cleaned_text = '\n'.join(cleaned_lines)

# 大小写转换
if out_file_format.lower() == 'pdf':  # 转小写

1.8 布尔判断

if raw_text:          # 非空字符串为 True
if tables:            # 非空列表为 True
if file_path:         # 非 None 且非空为 True
if not file_path.lower().endswith('.pdf'):  # 取反

知识点:

  • Python 中的"真值测试"规则:
    • False, None, 0, "", [], {}, set() 等视为 False
    • 其他值视为 True

1.9 上下文管理器 (with 语句)

with open(out_file_path, 'w', encoding='utf-8') as f:
    f.write(content)

with pdfplumber.open(pdf_file) as pdf:
    pages = pdf.pages

知识点:

  • 自动管理资源的获取和释放
  • 即使发生异常也会正确关闭资源
  • 需要对象实现 __enter__()__exit__() 方法

2. 面向对象编程 (OOP)

2.1 类定义与初始化

class FileWriter:
    """
    文件写入类
    """
    
    def __init__(self, book: Book):
        self.book = book

知识点:

  • __init__() 是构造函数,创建对象时自动调用
  • self 代表实例本身,必须作为第一个参数
  • 类名使用大驼峰命名法 (PascalCase)

2.2 类的方法类型

实例方法 (最常用):

def save_pdf(self, out_file_path: str):
    # 使用 self 访问实例属性
    pass

知识点:

  • 第一个参数必须是 self
  • 可以访问和修改实例属性

2.3 属性访问

class PDFTranslator:
    def __init__(self, model: Model):
        self.model = model      # 公共属性
        self._book = None       # 受保护属性 (约定)
        self.__private = None   # 私有属性 (名称改写)

知识点:

  • self.attribute - 公共属性,外部可访问
  • self._attribute - 受保护属性,约定不直接访问
  • self.__attribute - 私有属性,会被改写为 _ClassName__attribute

2.4 类型注解

def __init__(self, book: Book):
    self.book = book

def save_pdf(self, out_file_path: str) -> None:
    pass

知识点:

  • Python 3.5+ 支持类型提示
  • 参数: 类型 声明参数类型
  • -> 返回类型 声明返回值类型
  • 只是提示,不强制检查

2.5 组合模式

class PDFTranslator:
    def __init__(self, model: Model):
        self.model = model          # 组合 Model 对象
        self.writer = FileWriter()  # 组合 FileWriter 对象

知识点:

  • 一个类包含其他类的实例
  • 实现"has-a"关系 (翻译器有模型、有写入器)
  • 区别于继承的"is-a"关系

2.6 枚举类 (Enum)

from enum import Enum

class ContentType(Enum):
    TEXT = 1
    TABLE = 2
    IMAGE = 3

知识点:

  • 定义一组常量
  • 提高代码可读性和可维护性
  • 防止无效值

使用:

if content.content_type == ContentType.TEXT:
    # 处理文本

3. 模块与包管理

3.1 导入语句

绝对导入:

from ai_model.siliconflow_model import SiliconflowModel
from translator.book_translator import PDFTranslator

相对导入:

from .ai_model.model import Model
from ..book.book import Book

知识点:

  • from module import name - 导入特定名称
  • import module - 导入整个模块
  • as 可以给导入起别名

3.2 包结构

book_translate/
├── __init__.py          # 标记为包
├── ai_model/
│   ├── __init__.py
│   └── model.py
├── book/
│   ├── __init__.py
│   └── book.py
└── translator/
    ├── __init__.py
    └── pdf_parser.py

知识点:

  • __init__.py 使目录成为 Python 包
  • 可以包含包的初始化代码
  • Python 3.3+ 支持隐式命名空间包 (可以没有 __init__.py)

3.3 模块导入路径

import sys
import os

# 添加项目根目录到 sys.path
sys.path.append('/path/to/project')

知识点:

  • Python 按 sys.path 列表搜索模块
  • 当前目录 (.) 在 sys.path
  • 使用 PYTHONPATH 环境变量添加路径

3.4 __main__ 模块

if __name__ == '__main__':
    # 当直接运行此文件时执行
    main()

知识点:

  • __name__ 是内置变量
  • 直接运行时值为 '__main__'
  • 被导入时值为模块名
  • 用于编写可执行脚本和可导入模块

4. 核心第三方库详解

4.1 pdfplumber - PDF 解析库

安装: pip install pdfplumber

基本用法:

import pdfplumber

with pdfplumber.open('file.pdf') as pdf:
    # 获取所有页面
    pages = pdf.pages
    print(f'总页数: {len(pages)}')
    
    # 遍历每一页
    for page in pages:
        # 提取文本
        text = page.extract_text()
        print(text)
        
        # 提取表格
        tables = page.extract_tables()
        for table in tables:
            # table 是二维列表
            for row in table:
                for cell in row:
                    print(cell)

重要方法:

方法 说明 返回类型
pdfplumber.open(path) 打开 PDF 文件 PDF 对象
pdf.pages 获取所有页面 列表
page.extract_text() 提取页面文本 str
page.extract_tables() 提取页面表格 List[List[List[str]]]

项目中的应用:

with pdfplumber.open(pdf_file) as pdf:
    # 获取指定页数
    if pages is None:
        pages_arr = pdf.pages
    else:
        pages_arr = pdf.pages[:pages]  # 切片获取前 n 页
    
    for pdf_page in pages_arr:
        raw_text = pdf_page.extract_text()
        tables = pdf_page.extract_tables()

4.2 reportlab - PDF 生成库

安装: pip install reportlab

核心模块:

4.2.1 SimpleDocTemplate - 文档模板

from reportlab.platypus import SimpleDocTemplate
from reportlab.lib import pagesizes

doc = SimpleDocTemplate(
    'output.pdf',              # 文件名
    pagesize=pagesizes.letter, # 页面大小: letter, A4, A3 等
    leftMargin=72,             # 左边距 (1 英寸 = 72 点)
    rightMargin=72,            # 右边距
    topMargin=72,              # 上边距
    bottomMargin=72            # 下边距
)

常用页面大小:

  • pagesizes.letter - 美国信纸 (612x792 点)
  • pagesizes.A4 - A4 纸 (595x842 点)
  • pagesizes.A3 - A3 纸 (842x1190 点)

4.2.2 Paragraph - 段落

from reportlab.platypus import Paragraph
from reportlab.lib.styles import ParagraphStyle

# 创建样式
style = ParagraphStyle(
    name='SimSun',           # 样式名称
    fontName='SimSun',       # 字体名称
    fontSize=10,             # 字体大小 (点)
    leading=14,              # 行间距
    spaceBefore=6,           # 段前间距
    spaceAfter=6,            # 段后间距
    leftIndent=0,            # 左缩进
    rightIndent=0,           # 右缩进
    firstLineIndent=0        # 首行缩进
)

# 创建段落
paragraph = Paragraph(
    text='这是段落内容',
    style=style
)

参数说明:

参数 类型 说明
name str 样式名称,用于引用
fontName str 字体名称 (需先注册)
fontSize int/float 字体大小,单位点 (1 点 ≈ 0.35mm)
leading int/float 行间距,通常比 fontSize 大 20-40%
spaceBefore int/float 段落前的空白
spaceAfter int/float 段落后的空白
leftIndent int/float 左缩进
rightIndent int/float 右缩进
firstLineIndent int/float 首行缩进

4.2.3 Table - 表格

from reportlab.platypus import Table, TableStyle
from reportlab.lib import colors

# 准备数据 (二维列表)
data = [
    ['表头1', '表头2', '表头3'],
    ['数据1', '数据2', '数据3'],
    ['数据4', '数据5', '数据6']
]

# 创建表格
table = Table(
    data=data,                    # 表格数据
    colWidths=[100, 150, 120],    # 列宽列表
    rowHeights=20                 # 行高 (可选)
)

# 设置样式
table_style = TableStyle([
    # 格式: ('命令', (开始列, 开始行), (结束列, 结束行), 参数)
    ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#4472C4')),
    ('TEXTCOLOR', (0, 0), (-1, 0), colors.white),
    ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
    ('FONT', (0, 0), (-1, -1), 'SimSun'),
    ('FONTSIZE', (0, 0), (-1, -1), 11),
    ('TOPPADDING', (0, 0), (-1, -1), 8),
    ('BOTTOMPADDING', (0, 0), (-1, -1), 8),
    ('LEFTPADDING', (0, 0), (-1, -1), 12),
    ('RIGHTPADDING', (0, 0), (-1, -1), 12),
    ('BACKGROUND', (0, 1), (-1, -1), colors.HexColor('#D9E1F2')),
    ('GRID', (0, 0), (-1, -1), 1, colors.HexColor('#8EA9DB')),
    ('LINEBELOW', (0, 0), (-1, 0), 2, colors.HexColor('#2F5496')),
])

table.setStyle(table_style)

坐标系统:

  • (0, 0) - 左上角 (第一列, 第一行)
  • (-1, 0) - 右上角 (最后一列, 第一行)
  • (0, -1) - 左下角 (第一列, 最后一行)
  • (-1, -1) - 右下角 (最后一列, 最后一行)

常用命令:

命令 说明 参数
BACKGROUND 背景色 颜色对象
TEXTCOLOR 文字颜色 颜色对象
ALIGN 对齐方式 'LEFT', 'CENTER', 'RIGHT'
FONT 字体 字体名称字符串
FONTSIZE 字体大小 数字 (点)
TOPPADDING 上内边距 数字 (点)
BOTTOMPADDING 下内边距 数字 (点)
LEFTPADDING 左内边距 数字 (点)
RIGHTPADDING 右内边距 数字 (点)
GRID 网格线 线宽, 颜色
LINEBELOW 下边框线 线宽, 颜色
BOX 外边框 线宽, 颜色
VALIGN 垂直对齐 'TOP', 'MIDDLE', 'BOTTOM'

4.2.4 PageBreak - 分页符

from reportlab.platypus import PageBreak

pdf_data.append(PageBreak())  # 添加分页符

4.2.5 字体注册

from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont

# 注册 TrueType 字体
pdfmetrics.registerFont(TTFont('SimSun', 'simsun.ttc'))
pdfmetrics.registerFont(TTFont('SimHei', 'simhei.ttf'))

支持的中文字体:

  • 宋体: simsun.ttc
  • 黑体: simhei.ttf
  • 微软雅黑: msyh.ttc
  • 楷体: simkai.ttf

4.2.6 构建文档

pdf_data = []  # 内容列表

# 添加内容
pdf_data.append(paragraph)
pdf_data.append(table)
pdf_data.append(PageBreak())

# 构建 PDF
doc.build(pdf_data)

项目中的应用:

# 完整流程
pdf_data = []

for page in self.book.pages:
    for content in page.contents:
        if content.content_type == ContentType.TEXT:
            paragraph = Paragraph(text=content.translation, style=style)
            pdf_data.append(paragraph)
        elif content.content_type == ContentType.TABLE:
            table = Table(data=table_data, colWidths=[120] * num_columns)
            table.setStyle(table_style)
            pdf_data.append(table)
    
    # 添加分页符 (除最后一页)
    if page != self.book.pages[-1]:
        pdf_data.append(PageBreak())

doc.build(pdf_data)

4.3 pandas - 数据处理库

安装: pip install pandas

核心数据结构:

4.3.1 DataFrame

import pandas as pd

# 从列表创建 DataFrame
data = [
    ['苹果', '红色', 1.20],
    ['香蕉', '黄色', 0.50]
]
columns = ['水果', '颜色', '价格']

df = pd.DataFrame(data, columns=columns)
print(df)

输出:

   水果  颜色   价格
0  苹果  红色  1.20
1  香蕉  黄色  0.50

常用属性和方法:

属性/方法 说明 返回类型
df.columns 列名 Index 对象
df.values 数据数组 numpy.ndarray
df.values.tolist() 转换为嵌套列表 List[List]
df.head(n) 前 n 行 DataFrame
df.tail(n) 后 n 行 DataFrame
df.shape 行列数 Tuple[int, int]
df.info() 数据信息 None

项目中的应用:

# 将表格数据转换为 DataFrame
translation_df = pd.DataFrame(table_data[1:], columns=table_data[0])

# 转换回列表用于 reportlab
table_data = df.values.tolist()

4.4 loguru - 日志库

安装: pip install loguru

基本用法:

from loguru import logger

logger.debug('调试信息')
logger.info('普通信息')
logger.warning('警告信息')
logger.error('错误信息')
logger.critical('严重错误')

日志级别 (从低到高):

  1. TRACE - 跟踪
  2. DEBUG - 调试
  3. INFO - 信息
  4. SUCCESS - 成功
  5. WARNING - 警告
  6. ERROR - 错误
  7. CRITICAL - 严重

自定义配置:

from loguru import logger
import sys

# 清除默认处理器
logger.remove()

# 添加控制台输出
logger.add(
    sys.stdout,                          # 输出到标准输出
    level='DEBUG',                       # 日志级别
    format="<green>{time:YYYYMMDD HH:mm:ss}</green> | "
           "{process.name} | "
           "{thread.name} | "
           "<cyan>{module}</cyan>.<cyan>{function}</cyan>:<cyan>{line}</cyan> | "
           "<level>{level}</level>: "
           "<level>{message}</level>",
    colorize=True                        # 启用颜色
)

# 添加文件输出
logger.add(
    'app.log',                           # 日志文件
    level='DEBUG',                       # 日志级别
    encoding='UTF-8',                    # 编码
    rotation='10 MB',                    # 文件大小限制
    retention=20,                        # 保留天数
    format='{time:YYYYMMDD HH:mm:ss} - {message}'
)

格式化参数:

参数 说明 示例
{time} 时间 20260507 22:44:42
{level} 日志级别 INFO
{message} 日志消息 开始翻译文件
{module} 模块名 main
{function} 函数名 <module>
{line} 行号 43
{process.name} 进程名 MainProcess
{thread.name} 线程名 MainThread

高级功能:

# 自动捕获异常
@logger.catch
def risky_function():
    return 1 / 0

# 记录异常
try:
    risky_function()
except Exception as e:
    logger.exception(e)  # 记录异常堆栈

# 日志轮转
logger.add('app.log', rotation='1 week')    # 每周轮转
logger.add('app.log', rotation='100 MB')    # 每 100MB 轮转
logger.add('app.log', rotation='12:00')     # 每天中午轮转

# 日志保留
logger.add('app.log', retention='30 days')  # 保留 30 天
logger.add('app.log', retention='1 year')   # 保留 1 年

项目中的封装:

class MyLogger:
    def __init__(self):
        self.logger = logger
        self.logger.remove()
        
        # 控制台输出
        self.logger.add(sys.stdout, level='DEBUG', format=...)
        
        # 文件输出
        self.logger.add(log_file_path, level='DEBUG', rotation='10 MB', retention=20)
    
    def get_logger(self):
        return self.logger

log = MyLogger().get_logger()

# 使用
log.info('信息')
log.debug('调试')
log.error('错误')

4.5 PyYAML - YAML 配置文件解析

安装: pip install pyyaml

YAML 文件示例 (config.yaml):

siliconflow:
  model: deepseek-ai/DeepSeek-V3
  api_key: sk-xxxxxxxx
  base_url: https://api.siliconflow.cn

common:
  book: test/test.pdf
  file_format: PDF

读取配置:

import yaml

# 读取 YAML 文件
with open('config.yaml', 'r', encoding='utf-8') as f:
    config = yaml.safe_load(f)

# 访问配置
model = config['siliconflow']['model']
api_key = config['siliconflow']['api_key']
file_format = config['common']['file_format']

# 安全访问 (使用 get 方法)
file_format = config['common'].get('file_format', 'PDF')  # 默认值为 'PDF'

常用方法:

方法 说明
yaml.safe_load(stream) 安全加载 YAML (推荐)
yaml.load(stream, Loader=yaml.FullLoader) 加载 YAML (不推荐, 有安全风险)
yaml.dump(data) 将 Python 对象转为 YAML 字符串
yaml.safe_dump(data) 安全转储

项目中的封装:

class LoaderConfig:
    def __init__(self, config_path):
        self.config_path = config_path
    
    def load_config(self):
        with open(self.config_path, 'r', encoding='utf-8') as f:
            return yaml.safe_load(f)

# 使用
config = LoaderConfig('config.yaml').load_config()

4.6 argparse - 命令行参数解析

基本用法:

import argparse

parser = argparse.ArgumentParser(description='书籍自动翻译器')

# 添加参数
parser.add_argument('--book', type=str, help='需要翻译的书籍路径')
parser.add_argument('--file_format', type=str, default='PDF', help='输出格式')
parser.add_argument('--model_type', type=str, required=True, 
                   choices=['SiliconFlow', 'GLMModel'], 
                   help='选择模型')

# 解析参数
args = parser.parse_args()

# 访问参数
book_path = args.book
file_format = args.file_format
model_type = args.model_type

常用参数:

parser.add_argument(
    '--name',                  # 参数名 (长选项)
    '-n',                      # 短选项 (可选)
    type=str,                  # 参数类型 (str, int, float, bool)
    default='value',           # 默认值
    required=True,             # 是否必需
    choices=['A', 'B'],        # 可选值列表
    help='参数说明',            # 帮助信息
    action='store_true'        # 特殊动作 (不需要值)
)

action 参数:

说明 示例
store 存储值 (默认) --file pdfargs.file = 'pdf'
store_true 存储 True --verboseargs.verbose = True
store_false 存储 False --quietargs.quiet = False
append 追加到列表 --tag a --tag b['a', 'b']
count 计数 -v -v -v3

项目中的应用:

class ArgumentUtils:
    def __init__(self):
        self.parser = argparse.ArgumentParser(description='书籍自动翻译器')
        self.parser.add_argument('--model_name', type=str, default='deepseek-ai/DeepSeek-V3')
        self.parser.add_argument('--api_key', type=str, default='')
        self.parser.add_argument('--config', type=str, default='config.yaml')
        self.parser.add_argument('--model_type', type=str, required=True, 
                                choices=['SiliconFlow', 'GLMModel'])
        self.parser.add_argument('--book', type=str)
        self.parser.add_argument('--file_format', type=str, default='PDF')
    
    def parse_args(self):
        args = self.parser.parse_args()
        # 自定义验证逻辑
        if args.model_type == 'SiliconFlow' and not args.model_name and not args.api_key:
            self.parser.error('请指定模型名称和API密钥')
        return args

帮助信息:

python main.py --help

5. 项目架构与设计模式

5.1 项目结构

book_translate/
├── main.py                    # 入口文件
├── ai_model/                  # AI 模型模块
│   ├── model.py               # 模型基类
│   └── siliconflow_model.py   # SiliconFlow 实现
├── book/                      # 书籍数据模型
│   ├── book.py                # Book 类
│   ├── page.py                # Page 类
│   └── content.py             # Content 类
├── translator/                # 翻译器模块
│   ├── pdf_parser.py          # PDF 解析器
│   ├── book_translator.py     # 翻译控制器
│   └── file_writer.py         # 文件写入器
├── utils/                     # 工具模块
│   ├── argument_utils.py      # 命令行参数
│   ├── loader_config.py       # 配置加载
│   ├── log_utils.py           # 日志工具
│   └── exceptions.py          # 自定义异常
├── fonts/                     # 字体文件
│   └── simsun.ttc
├── test/                      # 测试文件
│   └── test.pdf
└── logs/                      # 日志目录
    └── translation.log

5.2 设计模式

5.2.1 策略模式 (Strategy Pattern)

应用场景: 不同输出格式的处理

class FileWriter:
    def save_book(self, out_file_path, out_file_format):
        if out_file_format.lower() == 'pdf':
            self.save_pdf(out_file_path)
        elif out_file_format.lower() == 'markdown':
            self.save_markdown(out_file_path)
        elif out_file_format.lower() == 'docx':
            self.save_docx(out_file_path)

优点:

  • 易于扩展新的输出格式
  • 符合开闭原则 (对扩展开放,对修改封闭)

5.2.2 工厂方法模式 (Factory Method)

应用场景: 创建不同的模型实例

if args.model_type == 'SiliconFlow':
    model = SiliconflowModel(model_name, api_key, api_base)
else:
    model = GLMModel(model_name, api_key, api_base)

5.2.3 模板方法模式 (Template Method)

应用场景: PDF 解析流程

def parse_pdf(pdf_file, pages=None):
    book = Book(pdf_file)
    with pdfplumber.open(pdf_file) as pdf:
        for pdf_page in pdf.pages:
            page = Page()
            # 提取文本
            text = pdf_page.extract_text()
            # 提取表格
            tables = pdf_page.extract_tables()
            # 处理内容
            page.add_content(text)
            book.add_page(page)
    return book

5.3 面向对象设计原则

单一职责原则 (SRP):

  • PDFParser 只负责解析 PDF
  • FileWriter 只负责文件写入
  • PDFTranslator 只负责翻译流程

依赖倒置原则 (DIP):

  • PDFTranslator 依赖抽象的 Model 接口
  • 不依赖具体的 SiliconflowModel 实现

开闭原则 (OCP):

  • 添加新的模型只需创建新的类
  • 不需要修改现有代码

6. 文件操作与路径处理

6.1 os 模块

常用函数:

import os

# 路径操作
os.path.dirname(__file__)                    # 获取文件所在目录
os.path.abspath(__file__)                    # 获取文件绝对路径
os.path.join(dir1, dir2, 'file.txt')         # 路径拼接
os.path.exists(path)                         # 检查路径是否存在
os.path.isfile(path)                         # 检查是否为文件
os.path.isdir(path)                          # 检查是否为目录
os.path.basename(path)                       # 获取文件名
os.path.splitext(path)                       # 分离文件名和扩展名

# 目录操作
os.mkdir(path)                               # 创建目录
os.makedirs(path, exist_ok=True)             # 递归创建目录
os.listdir(path)                             # 列出目录内容
os.chdir(path)                               # 切换工作目录
os.getcwd()                                  # 获取当前工作目录

# 文件操作
os.remove(path)                              # 删除文件
os.rename(old, new)                          # 重命名
os.path.getsize(path)                        # 获取文件大小

项目中的应用:

# 获取当前文件所在目录
current_dir = os.path.dirname(os.path.abspath(__file__))

# 构建字体文件路径
font_path = os.path.join(current_dir, '..', 'fonts', 'simsun.ttc')

# 创建日志目录
if not os.path.exists(log_dir):
    os.mkdir(log_dir)

# 获取文件名
filename = os.path.basename(self.book.book_path)

# 检查文件扩展名
if not file_path.lower().endswith('.pdf'):
    log.error('目前只支持PDF格式的文件')

6.2 文件读写

读取文件:

# 方式 1: with 语句 (推荐)
with open('config.yaml', 'r', encoding='utf-8') as f:
    content = f.read()              # 读取全部内容
    # lines = f.readlines()         # 读取所有行
    # line = f.readline()           # 读取一行

# 方式 2: 手动关闭 (不推荐)
f = open('file.txt', 'r', encoding='utf-8')
try:
    content = f.read()
finally:
    f.close()

写入文件:

# 写入模式
with open('output.md', 'w', encoding='utf-8') as f:
    f.write('# 标题\n')
    f.write('内容\n')

# 追加模式
with open('output.md', 'a', encoding='utf-8') as f:
    f.write('追加内容\n')

文件模式:

模式 说明
'r' 只读 (默认)
'w' 写入 (覆盖)
'a' 追加
'b' 二进制模式 (与以上组合)
'+' 读写模式

6.3 路径处理技巧

字符串替换:

# 替换文件扩展名
subfix = path[path.rindex('.'):]           # 获取扩展名: '.pdf'
new_path = path.replace(subfix, '_translated.md')

项目中的应用:

# 生成输出文件路径
if out_file_path is None:
    subfix = self.book.book_path[self.book.book_path.rindex('.'):]
    out_file_path = self.book.book_path.replace(subfix, '_translated.pdf')

7. 日志记录系统

7.1 日志的重要性

  • 记录程序运行状态
  • 调试问题
  • 监控系统健康
  • 审计和安全

7.2 日志级别选择

log.trace('最详细的调试信息')    # 开发阶段使用
log.debug('调试信息')           # 开发阶段使用
log.info('普通信息')            # 生产环境使用
log.warning('警告')             # 潜在问题
log.error('错误')               # 错误但程序继续运行
log.critical('严重错误')        # 程序可能无法继续

7.3 最佳实践

# ❌ 不好: 使用 print
print('开始翻译')

# ✅ 好: 使用日志
log.info('开始翻译文件:{file_path}')

# ❌ 不好: 吞掉异常
try:
    result = process()
except:
    pass

# ✅ 好: 记录异常
try:
    result = process()
except Exception as e:
    log.error(f'处理失败: {e}')
    log.exception(e)  # 记录堆栈信息

8. 配置管理

8.1 为什么需要配置文件

  • 分离代码和配置
  • 便于修改参数
  • 支持不同环境 (开发/测试/生产)
  • 避免硬编码敏感信息

8.2 YAML 配置示例

# config.yaml
siliconflow:
  model: deepseek-ai/DeepSeek-V3
  api_key: ${SILICONFLOW_API_KEY}  # 环境变量
  base_url: https://api.siliconflow.cn

common:
  book: test/test.pdf
  file_format: PDF
  timeout: 60

logging:
  level: DEBUG
  file: translation.log

8.3 配置优先级

# 1. 命令行参数 (最高优先级)
# 2. 配置文件
# 3. 代码默认值 (最低优先级)

file_format = args.file_format if args.file_format else config['common'].get('file_format', 'PDF')

9. 命令行参数处理

9.1 参数设计原则

必需参数:

parser.add_argument('--model_type', type=str, required=True, 
                   choices=['SiliconFlow', 'GLMModel'])

可选参数 (有默认值):

parser.add_argument('--file_format', type=str, default='PDF')

标志参数 (布尔值):

parser.add_argument('--verbose', action='store_true', 
                   help='启用详细输出')

9.2 参数验证

def parse_args(self):
    args = self.parser.parse_args()
    
    # 自定义验证逻辑
    if args.model_type == 'SiliconFlow':
        if not args.api_key:
            self.parser.error('SiliconFlow 模型需要提供 API 密钥')
    
    return args

9.3 使用示例

# 基本使用
python main.py --model_type='SiliconFlow'

# 指定文件
python main.py --model_type='SiliconFlow' --book='test.pdf'

# 指定输出格式
python main.py --model_type='SiliconFlow' --file_format='markdown'

# 查看帮助
python main.py --help

10. 异常处理

10.1 自定义异常

class PageOutRangeException(Exception):
    """页面超出范围异常"""
    def __init__(self, total_pages, requested_pages):
        self.total_pages = total_pages
        self.requested_pages = requested_pages
        super().__init__(
            f'请求的页面数 {requested_pages} 超过总页数 {total_pages}'
        )

使用:

if pages and pages > len(pdf.pages):
    raise PageOutRangeException(len(pdf.pages), pages)

10.2 异常捕获

# 捕获特定异常
try:
    result = 1 / 0
except ZeroDivisionError as e:
    log.error(f'除零错误: {e}')

# 捕获所有异常
try:
    process()
except Exception as e:
    log.error(f'未知错误: {e}')
    log.exception(e)  # 记录完整堆栈

# finally 块 (始终执行)
try:
    f = open('file.txt')
    content = f.read()
finally:
    f.close()  # 确保文件关闭

10.3 装饰器捕获异常

from loguru import logger

@logger.catch
def risky_function():
    return 1 / 0

# 相当于
def risky_function():
    try:
        return 1 / 0
    except Exception as e:
        logger.exception(e)
        return None

11. 类型提示 (Type Hints)

11.1 基本类型

def greet(name: str, age: int, height: float, is_active: bool) -> str:
    return f'{name} is {age} years old'

11.2 容器类型

from typing import List, Dict, Optional, Tuple

def process_data(
    items: List[str],           # 字符串列表
    config: Dict[str, int],     # 字典
    name: Optional[str] = None, # 可选参数 (可以是 None)
    point: Tuple[int, int]      # 元组
) -> List[int]:
    return [1, 2, 3]

11.3 项目中的应用

from typing import Optional

def parse_pdf(pdf_file: str, pages: Optional[int] = None) -> Book:
    """
    :param pdf_file: pdf文件路径
    :param pages: 可选的,需要翻译的前n页
    :return: 返回一个Book对象
    """
    pass

常用类型:

类型 说明 示例
int 整数 age: int = 25
float 浮点数 price: float = 1.20
str 字符串 name: str = 'Python'
bool 布尔值 flag: bool = True
List[T] 列表 items: List[str]
Dict[K, V] 字典 config: Dict[str, int]
Optional[T] 可选类型 name: Optional[str]
Tuple[T, ...] 元组 point: Tuple[int, int]
Any 任意类型 data: Any

12. 文件编码与字符处理

12.1 文件编码

# 读取文件时指定编码
with open('file.txt', 'r', encoding='utf-8') as f:
    content = f.read()

# 写入文件时指定编码
with open('file.txt', 'w', encoding='utf-8') as f:
    f.write('中文内容')

常见编码:

  • utf-8 - 通用编码 (推荐)
  • gbk - 简体中文 (Windows)
  • gb2312 - 简体中文
  • big5 - 繁体中文

12.2 字符串处理

去除空白:

text = '  Hello World  \n'
text.strip()        # 'Hello World'
text.lstrip()       # 'Hello World  \n'
text.rstrip()       # '  Hello World'

分割字符串:

# 按行分割
lines = text.splitlines()

# 按空格分割
words = text.split()

# 按指定字符分割
parts = text.split(',')

连接字符串:

# 使用 join (高效)
lines = ['line1', 'line2', 'line3']
text = '\n'.join(lines)

# 使用 f-string (推荐)
name = 'Python'
version = 3.9
text = f'{name} {version}'

12.3 列表推导式处理

# 过滤空行
lines = raw_text.splitlines()
cleaned_lines = [line.strip() for line in lines if line.strip()]

# 转换数据
data = ['1.20', '0.50', '0.80']
numbers = [float(x) for x in data]

# 嵌套列表
table = [
    ['苹果', '红色', '1.20'],
    ['香蕉', '黄色', '0.50']
]
columns = [row[0] for row in table]  # ['苹果', '香蕉']

附录

A. 常用 Python 内置函数

函数 说明 示例
len() 获取长度 len([1,2,3]) → 3
type() 获取类型 type(123) → int
isinstance() 类型检查 isinstance(123, int) → True
str() 转字符串 str(123) → '123'
int() 转整数 int('123') → 123
float() 转浮点数 float('1.23') → 1.23
list() 转列表 list((1,2,3)) → [1,2,3]
dict() 转字典 dict(a=1)
range() 生成序列 range(3) → 0,1,2
enumerate() 枚举 enumerate(['a','b']) → (0,'a'),(1,'b')
zip() 压缩 zip([1,2], ['a','b']) → (1,'a'),(2,'b')
sorted() 排序 sorted([3,1,2]) → [1,2,3]
sum() 求和 sum([1,2,3]) → 6
max() 最大值 max([1,2,3]) → 3
min() 最小值 min([1,2,3]) → 1

B. 常用字符串方法

方法 说明
strip() 去除首尾空白
split() 分割字符串
join() 连接字符串
replace() 替换
find() 查找子串位置
startswith() 是否以...开始
endswith() 是否以...结束
upper() 转大写
lower() 转小写
capitalize() 首字母大写
title() 标题格式
format() 格式化字符串

C. 常用列表方法

方法 说明
append() 添加元素
extend() 扩展列表
insert() 插入元素
remove() 删除元素
pop() 弹出元素
sort() 排序
reverse() 反转
index() 查找索引
count() 计数

D. 常用字典方法

方法 说明
keys() 获取所有键
values() 获取所有值
items() 获取键值对
get() 获取值 (安全)
pop() 删除并返回值
update() 更新字典
clear() 清空字典

参考资源

官方文档

学习资源


文档版本: v1.0
最后更新: 2026-05-07
维护者: MrSponge

posted @ 2026-06-16 22:52  MrSponge  Views(10)  Comments(0)    收藏  举报