问题与目标
我第一次写 Python 时,最容易低估的不是语法,而是环境。
同一段代码,在终端里能运行,到了编辑器里却提示找不到包;明明刚执行过安装命令,程序还是报 ModuleNotFoundError;电脑里同时出现几个 Python,最后连自己正在使用哪一个解释器都说不清。
这些问题表面上像“环境玄学”,实际都在追问同一件事:
到底是哪一个 Python,在什么目录下,带着哪些依赖,执行了哪个文件?
如果这句话回答不出来,后面的代码越多,排查问题越被动。大模型项目的依赖通常比普通脚本更多,环境不稳定时,模型还没有开始调用,人已经先被解释器路径劝退了。
所以第一步不是记住多少语法,而是建立一个能重复验证的运行方式。
核心理解
Python 程序的运行可以拆成四个部分:
Python 解释器 + 项目目录 + 项目依赖 + Python 文件
- 解释器负责执行代码。
- 项目目录确定代码和相对路径从哪里开始寻找。
- 虚拟环境隔离这个项目需要的第三方依赖。
.py文件保存真正要执行的程序。
基础语法解决的是“代码怎么表达”,稳定环境解决的是“这段代码由谁来执行”。两者缺一个,程序都不算真正可控。
完成标准
完成这一篇后,应当能够独立完成这些操作:
- 确认 Python 版本和解释器路径。
- 为项目创建并激活虚拟环境。
- 使用当前解释器安装、查看和卸载依赖。
- 区分交互模式和脚本模式。
- 正确使用注释、缩进、变量和基础运算符。
- 接收用户输入,并用格式化字符串输出结果。
- 从终端稳定运行一个
.py文件。
程序如何变成运行结果
写下的 .py 文件保存在磁盘上,不会自己运行。执行 python app.py 时,操作系统会创建一个进程,把 Python 解释器和程序需要的数据加载到内存,再由 CPU 执行最终的机器指令。
以最常见的 CPython 为例,可以把过程简化为:
Python 源代码
↓ 解析与编译
字节码
↓ Python 虚拟机执行
操作系统进程
↓
CPU 计算 + 内存保存运行状态 + 磁盘保存文件
这里的“解释型语言”不等于源代码逐字符直接交给 CPU。CPython 通常会先把源代码编译成字节码,再执行字节码。初学阶段不需要记内部指令,但要知道解释器是源代码与运行环境之间的执行者。
可以查看当前 Python 实现和版本:
import platform
import sys
print(platform.python_implementation())
print(sys.version)
print(sys.executable)
输出中的实现名、版本和解释器路径,比“电脑上已经安装过 Python”更能准确说明当前程序由谁执行。
先把运行环境说清楚
确认 Python 来自哪里
先在终端执行:
python --version
python -c "import sys; print(sys.executable)"
有些系统使用 python3 命令,对应写成:
python3 --version
python3 -c "import sys; print(sys.executable)"
第一条命令确认版本,第二条命令打印当前解释器的真实路径。相比“我记得装过 Python”,路径更可信。
本阶段示例使用 Python 3.10 及以上版本可直接运行的类型标注语法。实际项目应按照项目约定选择版本,不必为了追逐版本号频繁更换解释器。
每个项目使用自己的虚拟环境
在项目目录下创建虚拟环境:
python -m venv .venv
macOS 或 Linux 激活方式:
source .venv/bin/activate
Windows PowerShell 激活方式:
.venv\Scripts\Activate.ps1
激活后再检查一次解释器路径。它应该指向当前项目的 .venv。
安装依赖时,优先写成:
python -m pip install 包名
这样可以明确让“当前这个 Python”调用自己的 pip,减少 python 和 pip 来自不同环境的情况。
常用依赖管理命令包括:
python -m pip list
python -m pip show 包名
python -m pip uninstall 包名
使用完虚拟环境后,可以退出:
deactivate
虚拟环境不是把 Python 复制得越多越好,而是让每个项目拥有清楚的依赖边界。以后一个项目需要某个库的旧版本,另一个项目需要新版本,它们不必互相打架。
编辑器只是入口,不是解释器本身
PyCharm、VS Code 或其他编辑器可以提供补全、调试和运行入口,但真正执行程序的仍然是所选的 Python 解释器。
因此编辑器里出现问题时,优先检查两个地方:
- 当前项目选择的解释器是不是
.venv中的 Python。 - 编辑器运行配置中的工作目录是不是项目目录。
这两个位置比反复点击“重新运行”更值得检查。
基础语法先掌握什么
Python 文件从上到下执行。缩进不是为了好看,而是语法的一部分。
第一阶段先抓住这些最小规则:
- 使用变量给数据起有意义的名字。
- 使用
#写必要的说明,不解释一眼就能看懂的代码。 - 使用四个空格表示同一层代码块。
- 使用
snake_case命名变量和函数。 - 使用
UPPER_CASE表示约定不修改的常量。 - 使用
print()观察程序当前得到的结果。
Python 的赋值更接近“让名字指向一个对象”,不是先准备一个固定类型的盒子。例如:
model_name = "demo-model"
temperature = 0.2
stream = True
model_name 指向字符串,temperature 指向浮点数,stream 指向布尔值。Python 会在运行时认识这些对象的类型,但这不代表类型不重要。相反,很多报错正是不同类型之间进行了不合理的操作。
交互模式和脚本模式
在终端输入 python,会进入交互模式:
>>> 1 + 2
3
>>> print("hello")
hello
交互模式适合快速验证一个表达式或查看对象,不适合保存完整程序。退出时可以输入 exit(),也可以使用终端对应的快捷键。
脚本模式把代码保存在 .py 文件中:
python app.py
脚本可以重复执行、纳入版本管理,也方便其他人复现。正式示例和项目代码都应该保存在脚本中,交互模式主要承担临时实验的角色。
注释、缩进和代码块
单行注释以 # 开始:
# 模型温度越低,输出通常越稳定
temperature = 0.2
三引号创建的是多行字符串,并不等同于专门的多行注释语法。函数、类和模块开头的三引号字符串可以作为文档字符串,供 help() 等工具读取。
Python 使用缩进表示代码层级:
enabled = True
if enabled:
print("功能已启用")
print("开始执行")
print("程序结束")
前两个 print() 属于 if,最后一个不属于。项目中统一使用四个空格,不混用制表符和空格。
标识符、关键字和命名
变量名、函数名和类名都属于标识符。基本规则是:
- 可以包含字母、数字和下划线。
- 不能以数字开头。
- 区分大小写,
name与Name是两个名字。 - 不能使用
if、for、class等关键字。
可以查看当前 Python 版本的关键字:
import keyword
print(keyword.kwlist)
命名不仅要合法,还要能说明含义:
# 含义模糊
x = 4096
# 含义清楚
max_context_length = 4096
常用约定包括:
- 变量和函数使用
snake_case。 - 类使用
PascalCase。 - 常量使用
UPPER_CASE。 - 以下划线开头的名字通常表示内部使用。
输入和输出
input() 接收终端输入,返回值始终是字符串:
name = input("请输入名称:")
print(f"你好,{name}")
需要数值时要主动转换:
max_tokens_text = input("请输入最大输出 Token 数:")
max_tokens = int(max_tokens_text)
print(f"最大输出长度设置为 {max_tokens}")
如果用户输入的不是整数,int() 会抛出异常。第一篇先认识这个边界,01.3 再系统处理异常。
print() 可以一次输出多个值,也能控制分隔符和结尾:
model = "demo-model"
temperature = 0.2
print(model, temperature, sep=" | ")
print("生成中", end="...")
print("完成")
项目代码中,f-string 通常比字符串拼接更清楚:
summary = f"模型={model}, 温度={temperature:.1f}"
常用运算符
算术运算符处理数值:
total = 10 + 5
average = total / 2
remainder = total % 4
power = 2 ** 3
需要注意,/ 返回浮点数,// 表示整除,% 得到余数。
比较运算符返回布尔值:
temperature = 0.2
print(temperature >= 0)
print(temperature <= 2)
print(temperature == 0.2)
print(temperature != 1.0)
逻辑运算符组合多个条件:
timeout = True
server_busy = False
enabled = True
is_valid = temperature >= 0 and temperature <= 2
should_retry = timeout or server_busy
is_disabled = not enabled
= 是赋值,== 才是比较。+=、-= 等复合赋值用于基于原值更新变量:
retry_count = 0
retry_count += 1
查看类型,而不是靠猜
type() 返回对象的具体类型,isinstance() 判断对象是否属于某个类型或一组类型:
temperature = 0.2
max_tokens = 512
print(type(temperature))
print(isinstance(max_tokens, int))
print(isinstance(temperature, (int, float)))
排查“字符串为什么不能和整数相加”这类问题时,先打印类型通常比反复修改运算符更有效。
in、== 和 is 不解决同一个问题
in 和 not in 判断成员是否存在:
supported_models = ["model-a", "model-b"]
print("model-a" in supported_models)
print("model-c" not in supported_models)
== 比较值是否相等,is 判断两个名字是否指向同一个对象:
left = ["python"]
right = ["python"]
alias = left
print(left == right) # True,内容相等
print(left is right) # False,不是同一个列表
print(left is alias) # True,指向同一个列表
业务数据比较通常使用 ==。判断空值使用 is None 或 is not None,不要用 is 比较普通字符串和数字的值。
运算符优先级不清楚时就加括号
算术、比较和逻辑运算符存在优先级。例如 and 先于 or 结合,但依赖记忆会增加阅读成本:
is_admin = False
has_permission = True
resource_public = True
can_access = is_admin or (has_permission and resource_public)
括号不仅控制计算顺序,也直接表达业务规则。复杂条件适合拆成带名称的布尔变量,而不是把所有判断挤在一行。
基础格式约定
Python 社区通常遵循 PEP 8。第一阶段先保持几条最实用的约定:
- 每层缩进使用四个空格。
- 顶层函数和类之间保留适当空行。
- 运算符两侧保留空格,逗号后保留空格。
- 一行只表达一个主要动作,不用分号堆叠语句。
- 行太长时使用括号自然换行,不用反斜杠硬接。
- Python 3 源文件默认使用 UTF-8,文件本身也应以 UTF-8 保存。
prompt = (
"请根据给定资料回答问题。"
"如果资料不足,请明确说明。"
)
格式规范不会改变运行结果,却会直接影响代码能否快速阅读、评审和修改。
可运行实现:生成一份模型调用配置摘要
这个例子不连接真实模型,只验证环境、变量、命名、缩进、字符串格式化和程序入口是否正常。
新建 app.py:
MODEL_NAME = "demo-chat-model"
question = "Python 环境为什么要隔离?"
temperature = 0.2
stream = True
summary = f"""模型调用配置
- 模型:{MODEL_NAME}
- 问题:{question}
- 温度:{temperature}
- 流式输出:{stream}
"""
print(summary)
在文件所在目录执行:
python app.py
预期输出:
模型调用配置
- 模型:demo-chat-model
- 问题:Python 环境为什么要隔离?
- 温度:0.2
- 流式输出:True
例子很小,但它完成了一次完整验证:终端找到了正确解释器,解释器找到了脚本,脚本成功创建变量并输出结果。
以后接入真实模型时,配置项会增加,依赖也会增加,但最底层的运行链路没有变。
动手练习:接收并检查一组模型参数
要求程序接收模型名、温度和最大输出长度,然后输出配置摘要。温度是否处于 0 到 2 之间,只需先用布尔值记录,下一篇再用分支给出不同处理。
model_name = input("模型名称:").strip()
temperature = float(input("温度:"))
max_tokens = int(input("最大输出 Token 数:"))
temperature_valid = 0 <= temperature <= 2
print("\n配置摘要")
print(f"模型:{model_name}")
print(f"温度:{temperature}")
print(f"最大输出:{max_tokens}")
print(f"温度有效:{temperature_valid}")
可以用下面三组输入检查程序:
| 模型名 | 温度 | 最大输出 | 观察重点 |
|---|---|---|---|
demo-model | 0.2 | 512 | 正常配置 |
demo-model | 2.5 | 512 | 布尔判断为假 |
demo-model | abc | 512 | 类型转换失败 |
第三组输入不是程序“突然坏了”,而是暴露了尚未处理的输入边界。这正是后续学习流程控制和异常处理的入口。
常见问题与排查
安装成功,不代表装进了当前环境
最常见的情况是:终端使用一个 Python,编辑器使用另一个 Python。包确实安装成功了,只是装到了程序没有使用的位置。
我的排查顺序是:
python -c "import sys; print(sys.executable)"
python -m pip --version
python -m pip list
先看路径,再看依赖,不凭感觉判断。
文件名会遮住标准库
如果把自己的文件命名为 json.py、random.py 或 typing.py,再执行 import json,Python 可能先导入当前目录下的同名文件。
这类错误看上去像标准库坏了,实际是命名冲突。项目文件名应该避开常用模块名。
相对路径取决于工作目录
open("data.txt") 寻找的是当前工作目录下的文件,不一定是 Python 文件旁边的文件。这个问题会在 01.3 的文件操作中继续解决。
变量能改类型,不代表应该随意改
下面的代码语法允许,但很难维护:
result = 10
result = "执行成功"
一个名字在同一段逻辑中反复表示不同含义,会增加理解成本。能运行只是最低要求,名字和含义稳定才方便继续修改。
小结
这一篇的完成标准,不是“成功打印一次 Hello World”,而是能够回答:
当前使用的是哪个 Python?
依赖安装在哪里?
程序从哪个目录运行?
怎样用一条命令重新执行?
当这些问题有明确答案时,Python 才从电脑里“装过的软件”,变成了我可以稳定使用的开发环境。
本篇检查清单:
- 能从终端打印 Python 版本和解释器路径。
- 能创建、激活和退出
.venv。 - 知道为什么优先使用
python -m pip。 - 能解释交互模式与脚本模式的用途差异。
- 能正确使用缩进、变量和 f-string。
- 知道
input()返回字符串。 - 能区分赋值、比较、算术和逻辑运算。
- 能使用
type()和isinstance()检查对象类型。 - 能解释
in、==和is的区别。 - 能用括号和基础格式规范提高可读性。
下一步的问题是:程序拿到不同的数据后,如何判断、循环、加工,再把重复逻辑封装成函数。
许可协议:CC BY-NC 4.0
更新于 3 小时前
觉得文章有帮助?点个赞吧!
0 条评论


