• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
sleepfish
博客园    首页    新随笔    联系   管理    订阅  订阅
PyScaffold新手使用手册

PyScaffold 新手使用手册

—— Python 工程化开发入门指南


1. PyScaffold 是什么?

PyScaffold 是一个 Python 项目脚手架工具,它能帮你:
✅ 自动生成标准化的项目结构(符合 Python 最佳实践)
✅ 集成常用工具(测试、文档、打包等)
✅ 减少手动配置,让你专注于代码开发

适合人群:

  • 刚接触 Python 工程化的新手
  • 想规范化项目结构的开发者
  • 需要快速搭建 Python 库或工具的人

2. 安装 PyScaffold

在终端(Windows 用 CMD/PowerShell,Mac/Linux 用 Terminal)运行:

pip install pyscaffold

⚠️ 建议使用 Python 3.7+,并确保 pip 已更新(pip install --upgrade pip)。


3. 快速创建项目

基础命令

putup my_project # 创建一个名为 my_project 的 Python 项目

这会生成以下目录结构:

my_project/
├── src/
│ └── my_project/ # 你的代码放在这里
│ └── init.py
├── tests/ # 测试代码
├── docs/ # 文档
├── setup.cfg # 项目配置(依赖、作者信息等)
├── pyproject.toml # 构建配置
└── README.md # 项目说明

常用选项

选项 作用 示例
--package 指定包名(默认同项目名) putup my_project --package mypkg
--pre-commit 启用 Git 提交前检查 putup my_project --pre-commit
--black 启用代码自动格式化 putup my_project --black
--license 添加开源协议(如 MIT) putup my_project --license MIT

完整命令示例:

putup my_project --pre-commit --black --license MIT


4. 项目结构详解

文件/目录 作用
src/my_project/ 项目主代码(__init__.py 是包入口)
tests/ 单元测试(PyScaffold 默认用 pytest)
docs/ 文档(默认支持 sphinx)
setup.cfg 项目元数据(名称、版本、依赖等)
pyproject.toml 构建系统配置(兼容 pip 和 build)

5. 开发流程

(1) 安装开发依赖

进入项目目录后运行:

pip install -e .[testing,docs] # -e 表示“可编辑模式”,修改代码无需重装

(2) 编写代码

  • 将你的 Python 模块放在 src/my_project/ 下。

  • 示例:创建 src/my_project/calculator.py:

    def add(a, b):
    return a + b

(3) 运行测试

PyScaffold 默认集成 pytest,直接运行:

pytest

测试文件示例(tests/test_calculator.py):

from my_project.calculator import add

def test_add():
assert add(1, 2) == 3

(4) 生成文档

cd docs && make html # 生成 HTML 文档,输出在 docs/_build/html/

(5) 打包发布

python -m build # 生成 dist/ 下的安装包
pip install dist/my_project-0.1.tar.gz # 本地测试安装


6. 进阶功能

(1) 启用 Git 版本控制

git init
git add .
git commit -m "Initial commit"

如果用了 --pre-commit,提交时会自动检查代码格式。

(2) 添加更多依赖

在 setup.cfg 的 install_requires 中添加:

install_requires =
numpy>=1.20
pandas

(3) 扩展 PyScaffold

通过插件支持 Django、Flask 等框架:

pip install pyscaffoldext-django # Django 项目模板
putup my_django_project --django


7. 常见问题

❌ 问题1:putup 命令找不到?
👉 确保 PyScaffold 已安装,或尝试 python -m pyscaffold.cli putup my_project。

❌ 问题2:运行 pytest 报错?
👉 检查是否安装了开发依赖(pip install -e .[testing])。

❌ 问题3:如何更新项目配置?
👉 直接修改 setup.cfg 或重新生成项目(需备份代码)。


8. 总结

  • PyScaffold 帮你自动化:项目初始化、测试配置、文档生成。
  • 适合场景:开发 Python 库、工具或团队协作项目。
  • 下一步学习:
    • 深入 pytest(官方文档)
    • 学习 setuptools 打包(教程)

🎉 现在你可以用 PyScaffold 快速启动一个专业的 Python 项目了!

Python 面向对象编程 (OOP) 代码模板

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
module_name.py

A description of what this module/class does.
"""

from typing import Optional, Any, List, Dict  # 类型注解支持


class BaseClass:
    """Base class documentation string.
    
    This is a base class that demonstrates proper Python OOP structure.
    """
    
    # 类常量 (全大写命名)
    CLASS_CONSTANT = "default_value"
    
    def __init__(self, param1: str, param2: int = 42) -> None:
        """Initialize the BaseClass.
        
        Args:
            param1: Description of param1
            param2: Description of param2 (default: 42)
        """
        self.public_attr = param1  # 公共属性
        self._protected_attr = param2  # 受保护属性 (单下划线前缀)
        self.__private_attr = "private"  # 私有属性 (双下划线前缀)
        
    def public_method(self) -> str:
        """Public method that does something.
        
        Returns:
            str: Description of return value
        """
        return f"Public: {self.public_attr}"
    
    def _protected_method(self) -> int:
        """Protected method (should only be used internally or by subclasses)."""
        return self._protected_attr * 2
    
    def __private_method(self) -> str:
        """Private method (name mangled, not accessible directly from outside)."""
        return f"Private: {self.__private_attr}"
    
    @property
    def calculated_property(self) -> float:
        """Example property that computes a value.
        
        Returns:
            float: The computed value
        """
        return self._protected_attr / 2
    
    @calculated_property.setter
    def calculated_property(self, value: float) -> None:
        """Property setter with validation."""
        if value <= 0:
            raise ValueError("Value must be positive")
        self._protected_attr = int(value * 2)
    
    @classmethod
    def from_alternative_constructor(cls, param: str) -> 'BaseClass':
        """Alternative constructor as a class method.
        
        Args:
            param: Description of parameter
            
        Returns:
            BaseClass: New instance of the class
        """
        return cls(param1=param, param2=len(param))
    
    @staticmethod
    def utility_function(text: str) -> str:
        """Static method that doesn't require instance access.
        
        Args:
            text: Input string
            
        Returns:
            str: Processed string
        """
        return text.upper()
    
    def __str__(self) -> str:
        """String representation of the object."""
        return f"BaseClass({self.public_attr})"
    
    def __repr__(self) -> str:
        """Unambiguous representation for debugging."""
        return f"BaseClass(param1={repr(self.public_attr)}, param2={self._protected_attr})"


class ChildClass(BaseClass):
    """Child class demonstrating inheritance."""
    
    def __init__(self, param1: str, param3: list, param2: int = 100) -> None:
        """Initialize the child class.
        
        Args:
            param3: New parameter specific to child class
        """
        super().__init__(param1, param2)  # 调用父类初始化
        self.param3 = param3
        
    def public_method(self) -> str:  # 方法重写
        """Override parent method with extended functionality."""
        parent_result = super().public_method()
        return f"Child: {parent_result} + {self.param3}"
    
    def child_specific_method(self) -> List[str]:
        """Method only available in child class."""
        return [str(item) for item in self.param3]


# 抽象基类示例
from abc import ABC, abstractmethod

class AbstractShape(ABC):
    """Abstract base class defining an interface for shapes."""
    
    @abstractmethod
    def area(self) -> float:
        """Calculate the area of the shape."""
        pass
    
    @abstractmethod
    def perimeter(self) -> float:
        """Calculate the perimeter of the shape."""
        pass


class Circle(AbstractShape):
    """Concrete implementation of AbstractShape for circles."""
    
    def __init__(self, radius: float) -> None:
        self.radius = radius
        
    def area(self) -> float:
        return 3.14159 * self.radius ** 2
    
    def perimeter(self) -> float:
        return 2 * 3.14159 * self.radius


# 混入类 (Mixin) 示例
class JSONMixin:
    """Mixin class adding JSON serialization capability."""
    
    def to_json(self) -> str:
        """Convert object to JSON string."""
        import json
        return json.dumps(self.__dict__)


class EnhancedClass(BaseClass, JSONMixin):
    """Class demonstrating multiple inheritance with a mixin."""
    pass


if __name__ == "__main__":
    # 示例用法
    base = BaseClass("test")
    print(base.public_method())
    
    child = ChildClass("child", [1, 2, 3])
    print(child.public_method())
    
    circle = Circle(5)
    print(f"Area: {circle.area():.2f}")
    
    enhanced = EnhancedClass("json")
    print(enhanced.to_json())




my_project/
├── src/
│   └── my_package/
│       ├── __init__.py         # 包初始化文件
│       ├── base_module.py      # 基础类定义
│       ├── subpackage/
│       │   ├── __init__.py
│       │   └── specialized.py # 特定功能类
│       └── utils.py           # 工具函数/类
├── tests/
│   ├── __init__.py
│   ├── test_base.py           # 单元测试
│   └── test_integration.py    # 集成测试
├── docs/                      # 文档
├── setup.py                   # 包配置
└── README.md                  # 项目说明


posted on 2025-06-09 17:18  江枫萤火aaa  阅读(110)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3