文章

1 · 环境、终端运行与第一个脚本

#001 · 2026-04-16 · Python

承上启下:这是系列的起点。从这里开始,我们用极客的方式重新认识 Python——不是 print('Hello World'),而是直接写一个有实际用途的 CLI 工具。

极客解析:先把数据流、控制流和模块边界跑通,再谈抽象;每段代码都围绕一个可执行 CLI 闭环展开。

痛点:大多数入门教程的"第一个程序"是 print("Hello World")——它什么问题都没解决。我们直接写一个有实际用途的工具。


环境架构

本机 Python 3.12+
    ├── venv(虚拟环境隔离)
    ├── pip(包管理)
    └── 你的 .py 脚本
         └── python3 script.py --flag  ← CLI 入口
工具 用途 安装方式
Python 3.12+ 解释器 brew install python / python.org
venv 项目隔离 内置,无需安装
argparse CLI 参数解析 内置标准库

快速搭建


python3 --version          # Python 3.12.x

# 创建项目并激活虚拟环境
mkdir geek-python && cd geek-python
python3 -m venv .venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate

# 确认环境隔离
which python3              # 应指向 .venv/bin/python3

实战演练场

第一个脚本不是 Hello World,而是一个系统信息探针——展示 Python 能做什么:

步步为营:核心逻辑自适应拆解

导师提示:这一篇只做一件事:把“第一个 Python 脚本”拆成能看见结果的 5 块小积木。每块都有原始源码、可运行演示和大白话解释;先跑小块,再看完整脚本。

Step 1:先认清脚本只依赖标准库

核心源码(逐字来自文末完整源码)

import argparse
import json
import os
import platform
import shutil
import sys
from datetime import datetime

可运行演示(补齐 Mock 数据与 print 反馈)

# 这一步先确认:我们只用 Python 标准库,不需要 pip install。
import argparse
import json
import os
import platform
import shutil
import sys
from datetime import datetime

modules = [argparse.__name__, json.__name__, os.__name__, platform.__name__, shutil.__name__, sys.__name__]
print("本脚本会用到这些标准库:")
for name in modules:
    print(f"- {name}")
print(f"当前时间来自 datetime:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")

大白话解析:新手第一怕就是环境装崩。这里先把依赖讲清楚:这些库都随 Python 自带,不用额外安装。它们像工具箱里的扳手、尺子和手电筒:os 看目录,platform 看系统,argparse 负责读命令行按钮。

Step 2:把电脑信息采集成一张字典

核心源码(逐字来自文末完整源码)

def get_system_info() -> dict[str, str]:
    """采集当前系统的关键运行时信息。"""
    return {
        "python_version": sys.version.split()[0],
        "platform":       platform.system(),
        "arch":           platform.machine(),
        "hostname":       platform.node(),
        "cpu_count":      str(os.cpu_count()),
        "cwd":            os.getcwd(),
        "timestamp":      datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
    }

可运行演示(补齐 Mock 数据与 print 反馈)

import argparse
import json
import os
import platform
import shutil
import sys
from datetime import datetime

def get_system_info() -> dict[str, str]:
    """采集当前系统的关键运行时信息。"""
    return {
        "python_version": sys.version.split()[0],
        "platform":       platform.system(),
        "arch":           platform.machine(),
        "hostname":       platform.node(),
        "cpu_count":      str(os.cpu_count()),
        "cwd":            os.getcwd(),
        "timestamp":      datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
    }

# 真实调用一次:把这台电脑的关键信息采集成字典。
info = get_system_info()
print("系统信息已经采集完成,先看 3 个最容易理解的字段:")
print(f"Python 版本:{info['python_version']}")
print(f"操作系统:{info['platform']}")
print(f"当前目录:{info['cwd']}")

大白话解析get_system_info() 像体检表生成器:它不直接打印,而是先把 Python 版本、系统平台、CPU 数量、当前目录这些信息装进字典。这样后面想输出表格或 JSON,都能复用同一份数据。

Step 3:用 PATH 地图检查命令是否存在

核心源码(逐字来自文末完整源码)

def check_tool(tool_name: str) -> None:
    """检查指定命令行工具是否存在于 PATH。"""
    path = shutil.which(tool_name)
    if path:
        print(f"  ✅  {tool_name:<12} → {path}")
    else:
        print(f"  ❌  {tool_name:<12} → not found")

可运行演示(补齐 Mock 数据与 print 反馈)

import shutil

def check_tool(tool_name: str) -> None:
    """检查指定命令行工具是否存在于 PATH。"""
    path = shutil.which(tool_name)
    if path:
        print(f"  ✅  {tool_name:<12}{path}")
    else:
        print(f"  ❌  {tool_name:<12} → not found")

# 检查 python3 是否能在终端里被找到。
# shutil.which 像是在 PATH 这张“工具地图”里找具体位置。
print("开始检查命令行工具:")
check_tool("python3")
check_tool("definitely-not-installed-tool")

大白话解析shutil.which() 可以理解成在终端的工具地图里找路牌。找得到就打印真实路径,找不到就明确告诉你 not found。这比让新手盲猜“为什么命令不能用”要友好得多。

Step 4:把字典排成终端表格

核心源码(逐字来自文末完整源码)

def print_table(info: dict[str, str]) -> None:
    """以对齐表格形式输出系统信息。"""
    width = 44
    print(f"\n  ┌{'─' * width}┐")
    print(f"  │{'  🐍 Python 系统探针':^{width}}│")
    print(f"  ├{'─' * width}┤")
    for key, val in info.items():
        label = key.replace("_", " ").title()
        print(f"  │  {label:<18} {val:<{width - 22}}│")
    print(f"  └{'─' * width}┘\n")

可运行演示(补齐 Mock 数据与 print 反馈)

def print_table(info: dict[str, str]) -> None:
    """以对齐表格形式输出系统信息。"""
    width = 44
    print(f"\n{'─' * width}┐")
    print(f"  │{'  🐍 Python 系统探针':^{width}}│")
    print(f"  ├{'─' * width}┤")
    for key, val in info.items():
        label = key.replace("_", " ").title()
        print(f"  │  {label:<18} {val:<{width - 22}}│")
    print(f"  └{'─' * width}\n")

# 用一份很小的假数据先练习表格输出,避免第一次就被系统字段吓到。
sample_info: dict[str, str] = {
    "python_version": "3.12.x",
    "platform": "Darwin/Linux/Windows",
    "cwd": "/your/project",
}
print_table(sample_info)

大白话解析:表格输出不是炫技,而是降低阅读成本。for key, val in info.items() 像逐行填写表格,:<18 这类格式控制负责把文字对齐,让终端结果看起来像一张干净清单。

Step 5:用 argparse 做脚本遥控器

核心源码(逐字来自文末完整源码)

def main() -> None:
    parser = argparse.ArgumentParser(
        description="系统信息探针",
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    parser.add_argument(
        "--json", action="store_true", help="以 JSON 格式输出"
    )
    parser.add_argument(
        "--check", metavar="TOOL", help="检查指定工具是否安装(如 git、docker)"
    )
    args = parser.parse_args()

    info = get_system_info()

    if args.check:
        print(f"\n  检查工具: {args.check}")
        check_tool(args.check)
        return

    if args.json:
        print(json.dumps(info, indent=2, ensure_ascii=False))
    else:
        print_table(info)

可运行演示(补齐 Mock 数据与 print 反馈)

import argparse

# argparse 是脚本的“遥控器”:不同按钮触发不同输出方式。
parser = argparse.ArgumentParser(
    description="系统信息探针",
    formatter_class=argparse.RawDescriptionHelpFormatter,
)
parser.add_argument("--json", action="store_true", help="以 JSON 格式输出")
parser.add_argument("--check", metavar="TOOL", help="检查指定工具是否安装(如 git、docker)")

# 教学演示里手动传入参数;真实脚本会自动读取终端参数。
args = parser.parse_args(["--check", "python3"])
print(f"是否请求 JSON 输出:{args.json}")
print(f"要检查的工具名:{args.check}")

大白话解析:CLI 参数就是脚本的遥控器。--json 是切换输出格式的按钮,--check python3 是检查工具的按钮。新手只要记住:参数先注册,再解析,最后根据参数决定走哪条分支。

极客实战:完整源码与运行

现在,把上面的积木拼起来,将以下完整代码放进你的编辑器,运行它。先看整体闭环,再回头逐段改参数,你会更容易建立工程直觉。

# sysinfo.py
"""
系统信息探针 —— 第一个真正有用的 CLI 工具。
用法:
    python3 sysinfo.py
    python3 sysinfo.py --json
    python3 sysinfo.py --check python
"""

import argparse
import json
import os
import platform
import shutil
import sys
from datetime import datetime


def get_system_info() -> dict[str, str]:
    """采集当前系统的关键运行时信息。"""
    return {
        "python_version": sys.version.split()[0],
        "platform":       platform.system(),
        "arch":           platform.machine(),
        "hostname":       platform.node(),
        "cpu_count":      str(os.cpu_count()),
        "cwd":            os.getcwd(),
        "timestamp":      datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
    }


def check_tool(tool_name: str) -> None:
    """检查指定命令行工具是否存在于 PATH。"""
    path = shutil.which(tool_name)
    if path:
        print(f"  ✅  {tool_name:<12}{path}")
    else:
        print(f"  ❌  {tool_name:<12} → not found")


def print_table(info: dict[str, str]) -> None:
    """以对齐表格形式输出系统信息。"""
    width = 44
    print(f"\n{'─' * width}┐")
    print(f"  │{'  🐍 Python 系统探针':^{width}}│")
    print(f"  ├{'─' * width}┤")
    for key, val in info.items():
        label = key.replace("_", " ").title()
        print(f"  │  {label:<18} {val:<{width - 22}}│")
    print(f"  └{'─' * width}\n")


def main() -> None:
    parser = argparse.ArgumentParser(
        description="系统信息探针",
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    parser.add_argument(
        "--json", action="store_true", help="以 JSON 格式输出"
    )
    parser.add_argument(
        "--check", metavar="TOOL", help="检查指定工具是否安装(如 git、docker)"
    )
    args = parser.parse_args()

    info = get_system_info()

    if args.check:
        print(f"\n  检查工具: {args.check}")
        check_tool(args.check)
        return

    if args.json:
        print(json.dumps(info, indent=2, ensure_ascii=False))
    else:
        print_table(info)


if __name__ == "__main__":
    main()

终端预期输出:

$ python3 sysinfo.py

  ┌────────────────────────────────────────────┐
  │              🐍 Python 系统探针              │
  ├────────────────────────────────────────────┤
  │  Python Version   3.12.3                   │
  │  Platform         Darwin                   │
  │  Arch             arm64                    │
  │  Hostname         my-macbook               │
  │  Cpu Count        10  │  Cwd              /Users/me/geek-python    │
  │  Timestamp        2026-04-16 13:00:00      │
  └────────────────────────────────────────────┘

$ python3 sysinfo.py --check git
  检查工具: git
  ✅  git          → /usr/bin/git

$ python3 sysinfo.py --json
{
  "python_version": "3.12.3",
  ...
}

核心概念速查

# 1. 变量与类型(无需声明,动态绑定)
name: str = "geek"          # 类型提示是给 IDE 看的,不影响运行
count: int = 42
ratio: float = 3.14
active: bool = True

# 2. 打印与格式化(f-string 是首选)
print(f"Hello, {name}! count={count}")

# 3. 脚本入口守卫(必须养成习惯)
# if __name__ == "__main__": main()  # 守卫示例(main 在完整脚本中定义)
print("变量与类型演示完成")

避坑指南

现象 解法
系统 Python 污染 全局安装包导致版本冲突 每个项目用 venv
文件名与模块同名 import random 找到自己的 random.py 避免与标准库同名
Windows 路径分隔符 \ 在字符串中转义 pathlib.Path 或原始字符串 r"C:\path"
print 无输出 缓冲区未刷新 print(..., flush=True)python3 -u

NexDo Time ⚡

5 分钟极客微操:给 sysinfo.py 增加 --watch N 参数,每隔 N 秒刷新一次输出(用 time.sleep + 循环),实现一个极简的实时系统监控面板。

Don’t wait for next time, do it in the next moment.