Week 02:Python 进阶 + Linux 工作流

Published 2026-07-26 02:00 5414 words 28 min read

This post is not yet available in English. Showing the original.
Week 02:Python 进阶 + Linux 工作流。fish-first 终端教学,面向 CachyOS、VS Code、uv 和 Python 学习路线。
Oh My Pi / weekly tutorial / week02-python-linux-workflow
miku@cachyos:~/Code/python-learning$ omp teach week02-python-linux-workflow --fish-first --step-by-step
source791 行教学文档
weekWeek 02
shellfish-first 命令版
backlink20 周计划

Week 02:Python 进阶 + Linux 工作流

返回主线计划:USTC 统计学 AI / 量化 20 周成长计划

本文命令默认使用 fish shell。如果你在 VS Code 终端里看到的不是 fish,可以先执行 fish 进入 fish;后续不再重复说明。目标不是把 Linux 背熟,而是把“写脚本、运行脚本、查看结果、提交 Git”变成稳定流程。

0. 本周详细教学:语法、规范、验收

本节不是追加在尾部的复习,而是本周正文的入口。先读这里,再做后面的命令和项目。

0.1 本周真正要学会什么

维度要求
知识点list/dict、模块、异常、argparse、pathlib、Git commit
代码语法能从空文件写出本周核心脚本,而不是只复制运行
程序规范函数拆分、路径清楚、输入输出明确、错误能解释
交付物src/data_summary.py
验收方式从 fish 终端运行命令,得到可复查的文件或指标

0.2 代码语法精讲

下面的代码不是最终答案,而是本周必须理解的最小骨架:

omppython
from argparse import ArgumentParser
from pathlib import Path

parser = ArgumentParser() parser.add_argument(“—input”, required=True) args = parser.parse_args() path = Path(args.input) if not path.exists(): raise SystemExit(f”missing input: {path}”) print(path.read_text(encoding=“utf-8”)[

])

读代码时按四步检查:输入从哪里来;中间变量的类型和 shape 是什么;函数或脚本输出什么;哪些错误应该显式报出来。

0.3 本周程序规范

  • 所有路径用相对路径或 `pathlib.Path`,不要写死 `/home/miku/...`。
  • 核心逻辑进 `src/`,notebook 只做探索和解释。
  • 每个脚本能从 fish 终端运行,并在 README 写出命令。
  • 输出必须落盘到 `reports/`、`figures/` 或 `outputs/`,不能只在屏幕上看。

0.4 本周练习分层

层级任务不合格表现合格验收
最小练习手写上面的最小骨架只在 notebook 里运行终端运行成功
标准练习把逻辑拆成函数/模块一个大脚本从头写到尾至少 2 个函数,职责清楚
项目练习生成本周交付物 src/data_summary.py只有屏幕输出文件落盘,可复查
复盘练习写 3 个错误和修复只写“已解决”写清报错、原因、修复、预防

0.5 本周和主线的连接

1. 本周目标

完成 Week 02 后,你应该能独立做到:

  1. 用 list comprehension / dict comprehension 写简洁的数据转换代码。
  2. 把重复逻辑封装成函数,而不是把所有代码堆在一个文件里。
  3. pathlib 处理文件路径,避免手动拼接字符串路径。
  4. 写一个可从命令行运行的 CSV 汇总脚本 src/data_summary.py
  5. 在 fish 终端里完成目录导航、文件检查、uv run 运行、Git status/add/commit。

文件布局

本周交付物建议放在:

ompprompt
week02-python-linux-workflow/
├── data/
│   └── scores.csv
├── notes/
│   └── week02-linux-git.md
├── src/
│   └── data_summary.py
├── .venv/
├── pyproject.toml
└── README.md

2. 前置要求

你需要已经完成 Week 01 的基础环境:

  • CachyOS / Arch 系 Linux 可正常打开终端。
  • VS Code 已安装,并能用 code . 打开当前目录。
  • uv 已安装。
  • Git 可用:git --version 能输出版本号。
  • 知道 Python 基础变量、列表、字典、for 循环、if 判断。

先检查工具:

ompfish
python --version
uv --version
git --version
pwd

解释:

命令 作用
python --version 查看当前终端能找到的 Python 版本
uv --version 确认 uv 可用
git --version 确认 Git 可用
pwd 打印当前位置,避免在错误目录创建项目

3. 创建 Week 02 项目目录

建议每周一个独立项目,这样 Git 提交、依赖和报告都清楚。

ompfish
mkdir -p ~/Code/python-learning/week02-python-linux-workflow
cd ~/Code/python-learning/week02-python-linux-workflow
mkdir -p src data notes reports
code .

逐句解释:

命令 含义
mkdir -p ... 创建目录;如果上级目录不存在就一起创建
cd ... 进入 Week 02 项目目录
mkdir -p src data notes reports 创建源码、数据、笔记、报告目录
code . 用 VS Code 打开当前项目

检查当前结构:

ompfish
pwd
ls

你应该看到类似:

ompprompt
data  notes  reports  src

4. 初始化 uv 项目和虚拟环境

在项目根目录执行:

ompfish
uv init
uv venv
source .venv/bin/activate.fish

解释:

命令 作用
uv init 生成 pyproject.tomlREADME.md、示例入口文件
uv venv 创建当前项目专用虚拟环境 .venv/
source .venv/bin/activate.fish 在 fish shell 中激活虚拟环境

激活后检查:

ompfish
which python
python --version

如果 which python 输出路径包含当前项目的 .venv/bin/python,说明环境正确。

fish 注意:不要在 fish 里执行 Bash / Zsh 版本的虚拟环境激活脚本;fish 应使用 source .venv/bin/activate.fish

本周需要 pandas 来读 CSV:

ompfish
uv add pandas

之后运行脚本时优先使用:

ompfish
uv run python src/data_summary.py --help

uv run 会自动使用项目环境,比“碰运气使用系统 Python”更稳。

5. fish 终端导航:从“知道在哪”开始

Linux 工作流第一件事不是命令多,而是永远知道自己在什么目录。

ompfish
pwd
ls
cd src
pwd
cd ..
ls data

解释:

命令 作用
pwd 打印当前目录
ls 列出当前目录文件
cd src 进入 src 子目录
cd .. 回到上一级目录
ls data 不进入 data,直接查看它里面有什么

常用路径写法:

写法 含义
. 当前目录
.. 上一级目录
~ 当前用户主目录,例如 /home/miku
~/Code 主目录下的 Code 文件夹
src/data_summary.py 当前目录下的相对路径

建议养成习惯:运行任何脚本前先看一眼:

ompfish
pwd
ls

如果当前目录不是项目根目录,先 cd 回来:

ompfish
cd ~/Code/python-learning/week02-python-linux-workflow

6. 创建练习 CSV 数据

可以先用 VS Code 新建 data/scores.csv,内容如下:

ompcsv
student,major,math,english,python
A,statistics,88,79,85
B,statistics,92,81,90
C,finance,75,86,78
D,finance,80,,82
E,statistics,95,88,

如果想用 fish 命令创建,也可以执行:

ompfish
printf 'student,major,math,english,python\nA,statistics,88,79,85\nB,statistics,92,81,90\nC,finance,75,86,78\nD,finance,80,,82\nE,statistics,95,88,\n' > data/scores.csv

检查文件:

ompfish
cat data/scores.csv
wc -l data/scores.csv

解释:

命令 作用
cat 把整个小文件打印出来,适合查看短文件
wc -l 统计行数;CSV 第一行表头也算一行

真实数据通常不建议用 cat 一次打印几万行。可以用:

ompfish
head data/scores.csv
tail data/scores.csv

head 看开头,tail 看结尾。

7. Python 进阶一:list comprehension

list comprehension 适合把“循环生成新列表”的代码写得更清楚。

普通写法:

omppython
scores = [88, 92, 75, 80, 95]
passed = []

for score in scores: if score >= 80: passed.append(score)

print(passed)

list comprehension 写法:

omppython
scores = [88, 92, 75, 80, 95]
passed = [score for score in scores if score >= 80]
print(passed)

读法是:

ompprompt
[要放进新列表的值 for 临时变量 in 原列表 if 条件]

常见例子:

omppython
names = ["alice", "bob", "cathy"]
upper_names = [name.upper() for name in names]

scores = [88, 92, 75, 80, 95] labels = [“pass” if score >= 80 else “review” for score in scores]

raw_values = [“88”, “92”, "", “80”] clean_values = [int(value) for value in raw_values if value != ""]

注意:不要为了炫技把太复杂的逻辑塞进一行。如果一行里同时有多层循环、多层条件,普通 for 循环更适合。

8. Python 进阶二:dict comprehension

dict comprehension 用来从已有数据生成字典。

omppython
names = ["math", "english", "python"]
scores = [88, 79, 85]
score_dict = {name: score for name, score in zip(names, scores)}
print(score_dict)

输出:

ompprompt
{'math': 88, 'english': 79, 'python': 85}

筛选字典:

omppython
score_dict = {"math": 88, "english": 79, "python": 85}
high_scores = {subject: score for subject, score in score_dict.items() if score >= 80}
print(high_scores)

输出:

ompprompt
{'math': 88, 'python': 85}

在数据分析脚本中,dict comprehension 常用于生成摘要结果:

omppython
missing_counts = {column: 0 for column in ["math", "english", "python"]}

9. Python 进阶三:函数

函数的作用是把一段有明确职责的逻辑命名,方便重复使用和测试。

不推荐把所有逻辑写成这样:

omppython
import pandas as pd

df = pd.read_csv(“data/scores.csv”) print(df.shape) print(df.isna().sum()) print(df.mean(numeric_only=True))

更推荐拆成函数:

omppython
from pathlib import Path

import pandas as pd

def load_csv(path: Path) -> pd.DataFrame: return pd.read_csv(path)

def summarize(df: pd.DataFrame) -> dict: return { “rows”: len(df), “columns”: len(df.columns), “missing_values”: int(df.isna().sum().sum()), “numeric_means”: df.mean(numeric_only=True).to_dict(), }

判断函数是否清楚,可以问三个问题:

  1. 函数名是否说明它做什么?
  2. 输入参数是否明确?
  3. 返回值是否明确?

对初学者来说,函数不需要一开始写得很抽象。先把“读取数据”“计算摘要”“打印摘要”拆开,就已经很好。

10. Python 进阶四:pathlib

pathlib 是 Python 处理路径的现代方式。

不要这样手动拼路径:

omppython
path = "data" + "/" + "scores.csv"

推荐这样:

omppython
from pathlib import Path

project_root = Path.cwd() data_path = project_root / “data” / “scores.csv” print(data_path)

常用方法:

写法 作用
Path.cwd() 当前运行命令的目录
Path("data/scores.csv") 创建相对路径对象
path.exists() 判断路径是否存在
path.parent 获取父目录
path.name 获取文件名
path.suffix 获取扩展名,例如 .csv

在 CLI 脚本里,用户传入的路径建议立刻转成 Path

omppython
csv_path = Path(args.csv)

11. 编写 CLI 脚本 src/data_summary.py

在 VS Code 中创建文件:

ompprompt
src/data_summary.py

写入下面代码:

omppython
from argparse import ArgumentParser
from pathlib import Path

import pandas as pd

def parse_args(): parser = ArgumentParser(description=“Summarize a CSV file.”) parser.add_argument(“csv”, help=“Path to the input CSV file”) return parser.parse_args()

def load_csv(path: Path) -> pd.DataFrame: if not path.exists(): raise FileNotFoundError(f”CSV file not found: {path}”) if path.suffix.lower() != “.csv”: raise ValueError(f”Expected a .csv file, got: {path}”) return pd.read_csv(path)

def build_summary(df: pd.DataFrame) -> dict: numeric_means = df.mean(numeric_only=True).to_dict() return { “rows”: len(df), “columns”: len(df.columns), “missing_values”: int(df.isna().sum().sum()), “numeric_means”: numeric_means, }

def print_summary(summary: dict) -> None: print(“CSV Summary”) print(”===========”) print(f”Rows: {summary[‘rows’]}”) print(f”Columns: {summary[‘columns’]}”) print(f”Missing values: {summary[‘missing_values’]}”) print(“Numeric column means:”)

plain for column, value in summary[“numeric_means”].items(): print(f”- {column}: {value:.2f}”)

def main() -> None: args = parse_args() csv_path = Path(args.csv) df = load_csv(csv_path) summary = build_summary(df) print_summary(summary)

if name == “main”: main()

这段脚本分成四层:

函数 职责
parse_args 读取命令行参数
load_csv 检查路径并读取 CSV
build_summary 计算行数、列数、缺失值、均值
print_summary 把结果打印给用户
main 串起完整流程

12. 运行 CLI 脚本

先看帮助:

ompfish
uv run python src/data_summary.py --help

你应该看到脚本说明和参数说明。

再运行实际数据:

ompfish
uv run python src/data_summary.py data/scores.csv

期望输出类似:

ompprompt
CSV Summary
===========
Rows: 5
Columns: 5
Missing values: 2
Numeric column means:
- math: 86.00
- english: 83.50
- python: 83.75

如果你已经激活虚拟环境,也可以运行:

ompfish
python src/data_summary.py data/scores.csv

但为了可复现,本教程更推荐在说明文档里写 uv run python ...

13. 常用 Linux 文件检查命令

本周不要求成为 Linux 专家,但这些命令会反复出现。

ompfish
pwd
ls
cat data/scores.csv
head data/scores.csv
tail data/scores.csv
wc -l data/scores.csv
grep statistics data/scores.csv

解释:

命令 适合场景
pwd 确认当前目录
ls 看目录内容
cat 查看很短的小文件
head 查看文件开头
tail 查看文件结尾
wc -l 统计行数
grep statistics ... 找包含 statistics 的行

复制、移动、删除文件要更谨慎:

ompfish
cp data/scores.csv data/scores_backup.csv
mv data/scores_backup.csv data/scores_copy.csv
rm data/scores_copy.csv

解释:

命令 作用 风险
cp 复制文件 可能覆盖同名文件
mv 移动或重命名文件 可能把文件移到意外位置
rm 删除文件 删除后通常不能轻松恢复

初学阶段,执行 rm 前先 ls 确认目标。

14. Git 基础:status / add / commit

在项目根目录初始化 Git:

ompfish
git init
git status

git status 是最重要的 Git 命令之一。任何不确定的时候先运行它。

建议创建 .gitignore,避免把虚拟环境提交进去。在 VS Code 新建 .gitignore,写入:

ompprompt
.venv/
__pycache__/
.ipynb_checkpoints/
*.pyc

再次检查:

ompfish
git status

把本周文件加入暂存区:

ompfish
git add pyproject.toml uv.lock README.md .gitignore src data notes
git status

如果某个文件不存在,Git 会提示 pathspec 错误。可以先用 ls 看实际文件,再重新 git add 存在的文件。

提交:

ompfish
git commit -m "Add week02 Python Linux workflow exercise"

提交后检查:

ompfish
git status
git log --oneline -3

期望看到:

ompprompt
nothing to commit, working tree clean

以及最近提交列表中包含你的提交信息。

15. 写学习笔记 notes/week02-linux-git.md

在 VS Code 创建:

ompprompt
notes/week02-linux-git.md

建议包含四块:

ompmarkdown
# Week 02 Linux + Git 笔记

今天学会的命令

  • pwd:查看当前目录
  • ls:查看文件
  • cd:切换目录
  • uv run:用项目环境运行 Python
  • git status:查看 Git 状态

今天写的脚本

  • src/data_summary.py:读取 CSV,输出行数、列数、缺失值、数值列均值。

遇到的问题

  • 问题:fish 中误用了 Bash 激活脚本。
  • 解决:使用 source .venv/bin/activate.fish。

下次要改进

  • 给脚本增加输出到 Markdown 文件的功能。

笔记不是为了凑字数,而是为了让两周后的你能复盘:当时怎么跑、哪里报错、怎么修。

16. 本周练习

练习 A:list comprehension

创建 src/comprehension_practice.py,完成:

  1. 给定分数列表 [58, 72, 81, 90, 45, 66],生成及格分数列表。
  2. 生成所有分数的平方列表。
  3. 把名字列表 ['alice', 'bob', 'cathy'] 转成首字母大写。

运行:

ompfish
uv run python src/comprehension_practice.py

练习 B:dict comprehension

创建科目到分数的字典:

omppython
subjects = ["math", "english", "python"]
scores = [88, 79, 85]

要求生成:

ompprompt
{'math': 88, 'english': 79, 'python': 85}

再筛选出分数大于等于 80 的科目。

练习 C:增强 data_summary.py

给脚本增加一个可选参数:

ompfish
uv run python src/data_summary.py data/scores.csv --show-columns

当用户传入 --show-columns 时,额外打印列名。

提示:在 parse_args() 中增加:

omppython
parser.add_argument("--show-columns", action="store_true", help="Show CSV column names")

练习 D:Git 小循环

每完成一个小改动,就练习一次:

ompfish
git status
git add src/data_summary.py
git commit -m "Improve data summary script"
git status

重点不是提交很多次,而是理解:工作区、暂存区、提交记录分别是什么。

17. 验收检查

在 Week 02 项目根目录执行:

ompfish
pwd
ls
source .venv/bin/activate.fish
uv run python src/data_summary.py --help
uv run python src/data_summary.py data/scores.csv
git status

你应能确认:

  • pwd 位于 week02-python-linux-workflow 项目目录。
  • ls 能看到 srcdatanotespyproject.toml
  • source .venv/bin/activate.fish 不报错。
  • uv run python src/data_summary.py --help 能显示帮助。
  • uv run python src/data_summary.py data/scores.csv 能输出行数、列数、缺失值数量、数值列均值。
  • git status 能解释当前哪些文件未提交,或显示工作区干净。

18. 常见错误

错误 1:fish 中激活环境报语法错误

错误原因:执行了 Bash / Zsh 激活脚本。

fish 正确命令:

ompfish
source .venv/bin/activate.fish

错误 2:ModuleNotFoundError: No module named 'pandas'

原因:当前环境没有安装 pandas,或没有使用项目环境运行。

修复:

ompfish
cd ~/Code/python-learning/week02-python-linux-workflow
uv add pandas
uv run python src/data_summary.py data/scores.csv

错误 3:CSV file not found

原因:路径相对于当前目录解释,你可能不在项目根目录。

检查:

ompfish
pwd
ls data

如果 data/scores.csv 不存在,就回到正确目录或重新创建文件。

错误 4:Git 把 .venv/ 也显示为待提交

原因:忘记写 .gitignore

修复:

ompfish
printf '.venv/\n__pycache__/\n.ipynb_checkpoints/\n*.pyc\n' > .gitignore
git status

如果 .venv/ 已经被 git add,先取消暂存:

ompfish
git restore --staged .venv

错误 5:git commit 提示身份未知

Git 第一次提交可能要求配置姓名和邮箱。用你的真实或常用学习身份配置:

ompfish
git config --global user.name "Miku"
git config --global user.email "miku@example.com"

然后重新提交。

19. 下一步

下一周进入 NumPy / Pandas。你会把本周的“能读 CSV 并打印摘要”升级成真正的数据处理流程:读取真实表格、处理缺失值、做分组统计、保存清洗后的数据,并为 Week 04 的 EDA 报告准备数据基础。

plain

If you enjoyed this, leave a comment~

© 2026 江无没有月 @miku
Powered by theme astro-koharu · Inspired by Shoka