File size: 3,294 Bytes
a5fd608
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#!/usr/bin/env python3
"""
从 environment-linux.yml 生成 requirements.txt
YAML 中的版本号优先级最高
未指定版本号时查询当前环境的实际版本
排除 python 和 pip
"""

import os
from datetime import datetime
import yaml
from importlib.metadata import version, PackageNotFoundError


# 排除的包(不加入 requirements.txt)
EXCLUDE_PACKAGES = {"python", "pip"}


def get_installed_version(package_name):
    """获取包的安装版本,未安装返回 None"""
    try:
        return version(package_name)
    except PackageNotFoundError:
        return None


def parse_package_string(dep):
    """
    解析包字符串,返回 (包名, yaml版本号或None)
    例如: "tensorflow=2.15.0" -> ("tensorflow", "2.15.0")
          "numpy" -> ("numpy", None)
    """
    if "=" in dep:
        parts = dep.split("=")
        pkg_name = parts[0]
        pkg_version = parts[1]
        return pkg_name, pkg_version
    else:
        return dep, None


def parse_environment_yml(filepath):
    """解析 environment-linux.yml,提取包列表和版本信息"""
    with open(filepath, "r") as f:
        env = yaml.safe_load(f)

    packages = []

    for dep in env.get("dependencies", []):
        if isinstance(dep, str):
            # 简单字符串格式:package 或 package=version
            pkg_name, yaml_version = parse_package_string(dep)
            if pkg_name not in EXCLUDE_PACKAGES:
                packages.append((pkg_name, yaml_version))
        elif isinstance(dep, dict) and "pip" in dep:
            # pip 子列表
            for pip_dep in dep["pip"]:
                pkg_name, yaml_version = parse_package_string(pip_dep)
                if pkg_name not in EXCLUDE_PACKAGES:
                    packages.append((pkg_name, yaml_version))

    return packages


def main():
    yml_file = "environment-linux.yml"
    output_file = "requirements.txt"

    print(f"读取 {yml_file}...")
    packages = parse_environment_yml(yml_file)
    print(f"发现 {len(packages)} 个包(排除 {EXCLUDE_PACKAGES})")

    lines = []
    for pkg_name, yaml_version in packages:
        if yaml_version:
            # YAML 中有版本号,优先使用
            lines.append(f"{pkg_name}=={yaml_version}")
            print(f"  ✓ {pkg_name}=={yaml_version} (来自 YAML)")
        else:
            # YAML 中没有版本号,查询当前环境
            env_version = get_installed_version(pkg_name)
            if env_version:
                lines.append(f"{pkg_name}=={env_version}")
                print(f"  ✓ {pkg_name}=={env_version} (来自当前环境)")
            else:
                lines.append(pkg_name)
                print(f"  ⚠ {pkg_name} (未安装,无版本号)")

    # 添加头部注释
    header_lines = [
        f"# Generated from {yml_file}",
        f"# Timestamp: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
        f"# Environment: {os.environ.get('ENV', 'unknown')}",
        "#",
    ]

    # 合并所有行
    all_lines = header_lines + lines

    with open(output_file, "w") as f:
        f.write("\n".join(all_lines) + "\n")

    print(f"\n已生成 {output_file}:")
    print("-" * 40)
    print("\n".join(all_lines))
    print("-" * 40)


if __name__ == "__main__":
    main()