FiftyOne代码风格指南 fiftyone-code-style

FiftyOne代码风格指南是一套完整的Python编码规范,专门为FiftyOne计算机视觉数据集管理框架设计。该指南详细规定了模块结构、导入组织、文档字符串格式、私有函数命名、延迟导入策略、错误处理模式和代码质量检查清单。适用于开发者为FiftyOne贡献代码、开发插件或编写与FiftyOne代码库集成的Python程序时遵循,确保代码风格统一、可维护性强。关键词:FiftyOne, Python代码规范, 计算机视觉, 数据集管理, 代码风格, 开发指南, 开源贡献

计算机视觉 0 次安装 0 次浏览 更新于 3/1/2026

name: fiftyone-code-style description: 编写遵循FiftyOne官方规范的Python代码。适用于为FiftyOne做贡献、开发插件或编写与FiftyOne代码库集成的代码时使用。

FiftyOne 代码风格指南

模块模板

"""
模块描述。

| Copyright 2017-2025, Voxel51, Inc.
| `voxel51.com <https://voxel51.com/>`_
|
"""
# 标准库
import logging
import os

# 第三方库
import numpy as np

# eta (Voxel51工具库)
import eta.core.utils as etau

# FiftyOne
import fiftyone.core.fields as fof
import fiftyone.core.labels as fol
import fiftyone.core.utils as fou

logger = logging.getLogger(__name__)


def public_function(arg):
    """公共API函数。"""
    return _helper(arg)


def _helper(arg):
    """私有辅助函数(下划线前缀)。"""
    return arg

导入组织

分为四组,每组内按字母顺序排列:

组别 示例
1. 标准库 import logging, import os
2. 第三方库 import numpy as np, from PIL import Image
3. eta包 import eta.core.utils as etau
4. FiftyOne import fiftyone.core.labels as fol

FiftyOne 导入别名

模块 别名
fiftyone fo
fiftyone.core.labels fol
fiftyone.core.fields fof
fiftyone.core.media fom
fiftyone.core.storage fos
fiftyone.core.utils fou
fiftyone.utils.image foui
fiftyone.utils.video fouv

文档字符串(Google风格)

函数文档字符串

def get_operator(operator_uri, enabled=True):
    """获取指定URI的操作符。

    Args:
        operator_uri: 操作符URI
        enabled (True): 是否仅包含启用的操作符(True)、仅包含禁用的操作符(False)或所有操作符("all")

    Returns:
        一个 :class:`fiftyone.operators.Operator` 实例

    Raises:
        ValueError: 如果找不到操作符
    """

类文档字符串

class ImageMetadata(Metadata):
    """用于存储图像样本元数据的类。

    Args:
        size_bytes (None): 图像在磁盘上的大小,单位字节
        mime_type (None): 图像的MIME类型
        width (None): 图像宽度,单位像素
        height (None): 图像高度,单位像素
    """

关键模式:

  • 带默认值的参数:参数名 (默认值): 描述
  • 多行描述:缩进续行
  • 交叉引用::class:fiftyone.module.Class``

私有函数

# 公共API委托给私有辅助函数
def build_for(cls, path_or_url, mime_type=None):
    """为给定文件构建Metadata对象。"""
    if path_or_url.startswith("http"):
        return cls._build_for_url(path_or_url, mime_type=mime_type)
    return cls._build_for_local(path_or_url, mime_type=mime_type)

# 私有:下划线前缀,目的明确
def _build_for_local(cls, filepath, mime_type=None):
    """本地文件内部辅助函数。"""
    size_bytes = os.path.getsize(filepath)
    if mime_type is None:
        mime_type = etau.guess_mime_type(filepath)
    return cls(size_bytes=size_bytes, mime_type=mime_type)

延迟导入

使用 fou.lazy_import() 处理可选/重量级依赖:

# 基本延迟导入
o3d = fou.lazy_import("open3d", callback=lambda: fou.ensure_package("open3d"))

# 使用ensure_import处理pycocotools
mask_utils = fou.lazy_import(
    "pycocotools.mask", callback=lambda: fou.ensure_import("pycocotools")
)

# 内部模块延迟导入
fop = fou.lazy_import("fiftyone.core.plots.plotly")

何时使用:

  • 重量级包(open3d, tensorflow, torch)
  • 可选依赖(pycocotools)
  • 防止循环导入

防护模式

使用 hasattr() 进行条件行为检查:

# 检查可选属性
if hasattr(label, "confidence"):
    if label.confidence is None or label.confidence < threshold:
        label = label.__class__()

# 检查配置属性
if hasattr(eval_info.config, "iscrowd"):
    crowd_attr = eval_info.config.iscrowd
else:
    crowd_attr = None

# 动态状态初始化
if not hasattr(pb, "_next_idx"):
    pb._next_idx = 0
    pb._next_iters = []

错误处理

使用 logger.warning() 处理非致命错误:

# 非致命:警告并继续
try:
    for target in fo.config.logging_debug_targets.split(","):
        if logger_name := target.strip():
            loggers.append(logging.getLogger(logger_name))
except Exception as e:
    logger.warning(
        "解析日志调试目标'%s'失败:%s",
        fo.config.logging_debug_targets,
        e,
    )

# 缺少可选导入
try:
    import resource
except ImportError as e:
    if warn_on_failure:
        logger.warning(e)
    return

# 优雅降级
try:
    mask = etai.render_instance_image(dobj.mask, dobj.bounding_box, frame_size)
except:
    width, height = frame_size
    mask = np.zeros((height, width), dtype=bool)

避免冗余实现

在编写新函数之前,检查FiftyOne是否已提供该功能。

fiftyone.core.utils (fou) 中的常用工具

函数 用途
fou.lazy_import() 延迟模块加载
fou.ensure_package() 安装缺失包
fou.ensure_import() 验证导入可用性
fou.extract_kwargs_for_class() 为类拆分关键字参数
fou.load_xml_as_dict() 解析XML为字典
fou.get_default_executor() 获取线程池执行器

eta.core.utils (etau) 中的常用工具

函数 用途
etau.guess_mime_type() 检测文件MIME类型
etau.is_str() 检查是否为字符串
etau.ensure_dir() 创建目录(如果缺失)
etau.ensure_basedir() 创建父目录
etau.make_temp_dir() 创建临时目录

编写新代码前

  1. 搜索现有模块 查找类似功能:

    grep -r "def 你的函数名" fiftyone/
    grep -r "相似关键字" fiftyone/core/utils.py
    
  2. 首先检查这些模块:

    • fiftyone.core.utils - 通用工具
    • fiftyone.core.storage - 文件/云操作
    • fiftyone.utils.* - 格式特定工具
    • eta.core.utils - 底层辅助函数
  3. 冗余实现的红旗:

    • 文件路径操作 → 检查 os.pathetau
    • JSON/字典操作 → 检查 eta.core.serial
    • 图像操作 → 检查 fiftyone.utils.image
    • 类型检查 → 检查 etau.is_str()

代码验证清单

提交代码前,验证:

风格合规性

  • [ ] 模块有版权头部文档字符串
  • [ ] 导入分4组(标准库 → 第三方 → eta → fiftyone)
  • [ ] 每组内导入按字母顺序排列
  • [ ] FiftyOne导入使用标准别名(fol, fou等)
  • [ ] 日志记录器定义为 logger = logging.getLogger(__name__)
  • [ ] Google风格文档字符串,包含Args/Returns/Raises
  • [ ] 私有函数以 _ 为前缀

代码质量

  • [ ] 无冗余实现(已检查现有工具)
  • [ ] 重量级导入使用 fou.lazy_import()
  • [ ] 可选属性使用 hasattr() 防护
  • [ ] 非致命错误使用 logger.warning()
  • [ ] 无裸 except:(尽可能指定异常类型)

测试

# 运行代码检查
pylint fiftyone/你的模块.py

# 检查风格
black --check fiftyone/你的模块.py

# 运行测试
pytest tests/unittests/你的测试.py -v

快速参考

模式 约定
模块结构 文档字符串 → 导入 → 日志记录器 → 公共 → 私有 → 类
私有函数 _前缀,模块级别,小而专注
文档字符串 Google风格,包含Args/Returns/Raises
错误处理 try/except + logger.warning() 处理非致命错误
延迟导入 fou.lazy_import() 用于可选依赖
防护模式 hasattr() 检查条件行为
导入别名 fol, fof, fom, fos, fou
常量 大写字母,私有:_大写字母
类继承 显式 class Foo(object):
冗余检查 首先搜索 fou, etau, 现有模块