
Python教程:从安装环境到写出第一个实用脚本
Python 常被用于自动化、数据处理、测试、网站后端和 AI 应用。它语法相对简洁,标准库也覆盖了许多日常任务,因此很适合作为第一门编程语言。不过,“代码看起来容易”不等于不用理解环境、输入和失败情况。一个能长期使用的脚本,除了完成任务,还应当让使用者知道它会读取什么、会修改什么,以及出错时该如何判断。
本文从安装 Python 和创建项目环境开始,最后写出一个可运行的文件清单脚本:扫描指定目录,把文件路径、大小和修改时间保存为 JSON。这个例子默认只读取文件信息,不删除或修改被扫描的文件,适合用来学习命令行参数、路径处理、异常处理和输出文件等基础实践。
一、Python 适合做什么
Python 可以用来处理许多“重复、规则明确、输入输出清楚”的任务,例如:
- 文件自动化:批量整理文件名、统计目录内容、转换文本格式。
- 数据处理:读取 CSV 或 JSON,清洗数据,生成汇总结果。
- 接口与服务:编写网站后端、调用网络 API 或构建小型内部工具。
- 测试和运维:执行检查脚本、处理日志、辅助部署与排查问题。
- 科学计算和 AI:借助第三方库处理数值、图像、文本和模型任务。
Python 并非所有任务的最佳选择。对极低延迟、强实时性、资源受限设备或大量并行计算,可能需要其他语言或专门的运行时。Python 的执行速度也不能简单等同于 C、C++ 或 Rust。另一方面,实际程序的速度还取决于算法、数据量和调用的底层库,不能只凭语言名称判断。刚开始学习时,先把任务边界、输入和错误情况定义清楚,通常比过早优化更重要。
二、安装 Python 并确认命令可用
建议从 Python 官方下载页获取适用于自己操作系统的安装程序,或使用操作系统认可的软件包管理方式。安装时留意所选版本与平台的支持情况;学习本教程的基本内容,使用较新的 Python 3 版本即可。不要从来历不明的网站下载安装包,也不要把 Python 2 项目和 Python 3 项目混为一谈。Python 2 已停止维护,新项目应使用 Python 3。
安装完成后,打开终端验证版本。Windows 可以先尝试 py 启动器,也可以尝试 python;macOS 和 Linux 通常使用 python3。具体命令会受安装方式和系统配置影响:
python --version
python3 --version
py --version
不必要求这三条命令都成功。找到当前系统实际可用的一条即可。正常输出会包含类似 Python 3.x.x 的版本号。如果提示找不到命令,可能是尚未安装,也可能是安装目录没有加入 PATH 环境变量;Windows 还可以检查 Python Launcher 是否安装。修改 PATH 后,关闭并重新打开终端再试。不要通过随意删除系统文件或覆盖系统自带组件来解决命令冲突。
还可以用交互式解释器做一个最小验证。用上一步可用的命令启动 Python,例如:
python3
出现 >>> 提示符后输入:
print("你好,Python")
2 + 3
看到输出后,输入 exit() 退出。交互式环境适合尝试表达式,但正式任务建议写入脚本文件,以便保存、复用和检查。
三、创建项目与虚拟环境
虚拟环境是项目专属的 Python 环境,可让项目依赖与系统环境、其他项目分开。它不会自动让程序更安全,也不是容器或虚拟机;它主要解决 Python 包版本隔离问题。每个独立项目通常都适合有自己的虚拟环境。
先创建项目目录,再进入该目录。以下命令以常见终端为例:
mkdir python-file-report
cd python-file-report
python3 -m venv .venv
Windows 上如果使用 py,创建命令可以写成:
py -m venv .venv
激活环境的命令因操作系统和终端而异:
# Windows PowerShell
.venv\Scripts\Activate.ps1
# Windows 命令提示符
.venv\Scripts\activate.bat
# macOS / Linux
source .venv/bin/activate
激活成功后,终端提示符通常会显示 .venv。如果 PowerShell 因执行策略禁止运行激活脚本,不要为了单个项目贸然放宽整台机器的安全设置。可以改用命令提示符激活,或直接调用虚拟环境中的 Python:Windows 为 .venv\Scripts\python.exe,macOS 和 Linux 为 .venv/bin/python。
本教程最后的脚本只使用 Python 标准库,不需要安装第三方包。这也是一个有意的选择:简单任务优先减少外部依赖。若项目确实需要第三方包,激活虚拟环境后使用 python -m pip install 包名 安装,并在项目说明中记录依赖;不要在不清楚环境归属时盲目使用全局 pip。
四、写入并运行第一个脚本
在项目目录中创建文件 file_report.py,用文本编辑器写入代码。编辑器应保存纯文本文件,而不是富文本格式;文件扩展名要确实是 .py,避免被系统隐藏扩展名后保存成 file_report.py.txt。
下面的脚本接收一个目录和一个输出 JSON 文件路径,扫描目录中的普通文件,并记录相对路径、文件大小和修改时间。将代码完整复制到 file_report.py:
import argparse
import json
import os
import sys
from datetime import datetime, timezone
from pathlib import Path
def main():
parser = argparse.ArgumentParser(
description="扫描目录并生成 JSON 文件清单"
)
parser.add_argument(
"directory",
type=Path,
help="要扫描的目录"
)
parser.add_argument(
"output",
type=Path,
help="JSON 输出文件路径"
)
args = parser.parse_args()
root = args.directory.expanduser()
output = args.output.expanduser()
if not root.exists():
parser.error(f"目录不存在:{root}")
if not root.is_dir():
parser.error(f"给定路径不是目录:{root}")
records = []
walk_errors = []
def record_walk_error(error):
walk_errors.append(str(error))
try:
for current, directories, filenames in os.walk(
root,
onerror=record_walk_error,
followlinks=False
):
directories.sort()
filenames.sort()
current_path = Path(current)
for filename in filenames:
file_path = current_path / filename
try:
info = file_path.stat()
except OSError as error:
walk_errors.append(f"{file_path}: {error}")
continue
if not file_path.is_file():
continue
relative_path = file_path.relative_to(root)
modified = datetime.fromtimestamp(
info.st_mtime,
tz=timezone.utc
).isoformat()
records.append({
"path": relative_path.as_posix(),
"size_bytes": info.st_size,
"modified_utc": modified
})
output.parent.mkdir(parents=True, exist_ok=True)
with output.open("w", encoding="utf-8") as file:
json.dump(records, file, ensure_ascii=False, indent=2)
file.write("\\n")
except OSError as error:
print(f"无法写入输出文件:{error}", file=sys.stderr)
return 1
print(f"已记录 {len(records)} 个文件:{output}")
for error in walk_errors:
print(f"扫描警告:{error}", file=sys.stderr)
return 0
if __name__ == "__main__":
raise SystemExit(main())
脚本中的 argparse 负责读取命令行参数;Path 用于处理文件路径;os.walk 逐层遍历目录;json 将 Python 数据写成 JSON。main 函数把程序入口集中起来,最后用 raise SystemExit(main()) 将返回状态交给操作系统。成功时返回 0,遇到输出文件错误时返回 1。路径大小以字节记录,修改时间转换为 UTC,并带有时区信息。
在项目目录运行:
python3 file_report.py 要扫描的目录 report.json
Windows 如果使用 py,可运行:
py file_report.py 要扫描的目录 report.json
例如,扫描名为 documents 的目录:
python3 file_report.py documents report.json
也可以给出绝对路径。路径中含空格时,用引号括起来;Windows 路径可按终端规则书写:
python3 file_report.py "/home/alex/My Documents" report.json
执行成功后会看到记录数量和输出路径。用文本编辑器打开 report.json,可以看到类似这样的结构:
[
{
"path": "notes/todo.txt",
"size_bytes": 128,
"modified_utc": "2025-01-15T10:30:00+00:00"
}
]
示例里的时间和大小仅用于展示格式,实际结果取决于被扫描文件。输出中的路径相对于扫描根目录,使用正斜杠表示,便于在不同系统间查看;它不代表路径可在另一台机器上直接使用。
五、理解脚本的参数和边界
位置参数与帮助信息
运行脚本时必须提供两个位置参数:要扫描的目录和输出文件。少了参数,程序会显示用法提示,而不是猜测用户想扫描哪里。可以用以下命令查看帮助:
python3 file_report.py --help
argparse 会自动生成帮助文本,并负责将输入路径转换为 Path 对象。它不会替我们判断所有业务规则,因此代码仍需要检查目录是否存在、是否真的是目录。
路径参数可以是相对路径,也可以是绝对路径。相对路径以当前终端所在目录为基准,不一定以脚本文件所在位置为基准。如果运行时遇到“找不到目录”,先用 pwd(macOS/Linux)或 cd(Windows)确认当前目录,再检查路径拼写。
扫描范围和符号链接
脚本使用 os.walk(..., followlinks=False),默认不沿着目录符号链接继续遍历,避免链接形成循环或把扫描范围意外扩展到其他位置。不过,文件条目的处理使用了 Path.stat(),该操作会跟随文件符号链接获取目标信息。因此,符号链接文件可能以链接所在目录下的相对路径出现在报告中,但记录的大小和时间通常来自其指向的目标。若业务要求严格区分链接本身和目标,应使用 lstat() 等方式另行处理。
该脚本扫描的是当前进程有权访问的内容。权限不足时,部分目录或文件可能无法读取;程序会把可识别的扫描问题输出到标准错误,并继续处理其他可访问内容。操作系统、文件系统和 Python 版本等因素会影响具体错误表现,所以不能把“生成了报告”理解为“每个文件都一定成功扫描”。
对于会在扫描过程中不断变化的目录,结果也不是一个瞬间完成的原子快照:文件可能在读取目录列表之后被移动、改名或删除。因此,报告适合日常盘点,不适合作为文件系统一致性证明或取证结论。
输出位置
如果输出目录不存在,脚本会尝试创建它;如果输出文件已经存在,打开文件时会覆盖原内容。运行前应确认输出路径,尤其不要把重要文件误当成报告文件。将输出文件放在被扫描目录之外通常更清楚:若报告放在扫描目录内,第一次生成时可能还没有把它列入结果,但再次运行时旧报告可能被扫描进去。
输出写入失败时,程序会在标准错误中显示信息并以非零状态结束。可能的原因包括:没有写权限、目标位置不是普通文件、磁盘空间不足,或路径所在设备不可用。遇到失败时,不要仅凭终端里出现过“扫描了多少文件”就认定报告已经完整写入。
六、从脚本中认识几种 Python 基础写法
变量与数据结构
records 是一个列表,列表中的每项是字典。每个字典用键和值描述一个文件,例如 "size_bytes" 对应整数。Python 不要求在每次赋值时声明变量类型,但这不代表变量可以任意使用:后续代码仍必须按实际数据类型操作。明确的字段名能让 JSON 结果更容易被其他程序读取。
脚本中的 records.append(...) 会把一条记录加入列表。对于小型或中型目录,这种做法直观易懂;如果目录包含极大量文件,所有记录都保存在内存中,可能造成较高内存占用。此时可考虑逐条写入 JSON Lines(每行一个 JSON 对象),或采用数据库等更适合大规模数据的方案。不要在没有测量的情况下假设内存一定足够。
循环、条件和异常
for 循环逐个处理目录和文件名;if 语句检查路径状态;try/except 用于处理可能发生的操作系统错误。异常处理不应该把所有问题都隐藏起来。这里将无法读取的文件记为警告并继续扫描,同时对无法写出报告的情况直接返回失败状态,体现了两类错误的不同后果。
尽量捕获能够合理处理的异常,而不是用空白的 except: 把程序问题一概吞掉。调试时,错误信息是定位问题的重要线索;过度宽泛的异常处理会让输出看起来成功,实际数据却不完整。
编码与时间
打开输出文件时显式指定 encoding="utf-8",可以减少不同系统默认编码不一致造成的文本问题。ensure_ascii=False 让 JSON 中的中文按可读字符保存,而不是全部写成转义序列;两种形式都能表示 Unicode 文本。
文件系统提供的修改时间是时间戳。代码用带时区的 UTC 时间表示,避免把一个没有时区说明的本地时间误认为全球统一时间。需要展示本地时间时,可以在读取报告的一端做转换,而不应混淆数据实际采用的时区。
七、常见错误与排查方法
1. 把 Python 命令和文件名混淆
如果终端提示命令不存在,先验证解释器命令;如果提示找不到 file_report.py,则通常是当前目录不对,或文件名、扩展名写错。用 ls(macOS/Linux)或 dir(Windows)查看当前目录内容,再检查脚本文件是否真的在这里。
2. 激活了虚拟环境,却在别处安装包
安装依赖前先确认当前虚拟环境是否激活。更可靠的做法是使用虚拟环境解释器执行 -m pip,例如:
python -m pip --version
python -m pip install 包名
这能降低 pip 命令指向另一个 Python 环境的风险。本教程脚本不需要任何额外包,因此不必运行安装命令。
3. 路径里的空格没有加引号
终端会把未加引号的空格当作参数分隔符。例如,目录名是 My Documents 时,应将整个路径放在一对引号中。不同 shell 对引号、反斜杠和环境变量的处理细节不同;遇到问题时先用最简单的路径验证,再逐步加入复杂路径。
4. 把 Python 代码直接输进终端
终端运行的是命令,import argparse 这类内容属于 Python 代码。应将它保存到 .py 文件,然后让 Python 解释器运行文件;或者明确先启动交互式解释器,再输入 Python 语句。混淆这两种模式,常会导致看似奇怪的“命令找不到”错误。
5. 缩进混乱
Python 用缩进表示代码块。建议使用编辑器的自动缩进,并在同一个文件里保持一致;通常使用四个空格。不要随意混用制表符和空格。如果看到 IndentationError,检查出错行及其前后的代码块缩进,而不只是检查该行末尾。
6. JSON 结果不是 CSV
本脚本输出 JSON,不是可以直接按列显示的 CSV。JSON 适合保留结构化字段,便于程序读取;若需要电子表格格式,应另行使用标准库 csv 编写导出逻辑,并留意电子表格对以 =、+、- 或 @ 等字符开头的单元格内容可能有特殊解释。不要把未经检查的外部文本直接当作安全的表格数据。
八、安全用途与注意事项
本教程脚本只读取目录项和文件元数据,并写入指定的 JSON 文件;它不会执行被扫描文件,也不会读取文件内容。但“只读扫描”不等于完全没有风险。它仍会访问用户指定范围内的路径,可能触发权限错误、读取网络挂载目录中的元数据,或因为目录很大而消耗时间和内存。
- 只扫描明确授权的目录:不要把脚本用于自己无权访问的系统、共享盘或他人数据。
- 先确认输出路径:输出文件已存在时会被覆盖。报告应写到专用位置,重要数据应先备份。
- 不要把清单当成安全结论:文件名、大小和修改时间无法证明文件可信,也不能替代杀毒、权限审计或完整性校验。
- 注意报告本身也可能敏感:路径可能泄露用户名、项目名称或内部目录结构。分享报告前检查内容,并按组织的数据管理要求保存。
- 控制扫描规模:对特别大的目录,可先从测试目录开始。若需要扫描海量文件,应该评估运行时间、内存、存储空间和系统负载。
如果要扩展为删除、移动或重命名文件的工具,应另外设计预览模式、明确的范围限制、冲突处理和可恢复机制,并先在测试目录验证。不要因为清单脚本运行正常,就直接把它改成会批量修改文件的程序并用于重要数据。
九、接下来可以怎样扩展
当基础脚本能正常运行后,可以逐步加入功能,而不是一次改动很多地方:
- 增加参数,允许按扩展名筛选文件。
- 统计文件数量和总字节数,并将汇总信息一起写入 JSON。
- 增加排除目录选项,避免扫描缓存、虚拟环境或大型构建目录。
- 编写单元测试,检查路径处理、输出格式和异常分支。
- 将程序打包成可安装命令,或在自动化任务中定期运行。
扩展参数时要验证输入。例如,用户给出的扩展名可能没有点号、大小写也可能不同;应明确程序采用什么规则,并通过帮助文本说明。排除目录也要谨慎比较路径,避免仅因目录名相同就误排除不同位置。自动化任务则应记录退出状态和错误输出,不要只检查是否生成了文件。
结语
从安装 Python、验证解释器、创建虚拟环境,到保存和运行脚本,构成了一个可复用的开发起点。文件清单示例展示了如何用标准库接收参数、遍历路径、处理读取失败并生成 JSON,也说明了脚本的扫描范围、覆盖行为和资源边界。
编写实用脚本时,先让任务可重复、行为可说明、错误可发现。明确输入是什么,程序会修改什么,输出保存在哪里,以及失败时如何判断;这些习惯比单纯追求代码短小更重要。掌握这些基础之后,再按实际需求引入数据处理、网络请求或第三方库,会更容易写出可靠、可维护的 Python 程序。









