这是一个非常好的问题,因为它触及了 Python 解释器的工作方式,并引出了一个常见但容易混淆的术语。

我们来分两种情况详细解释:
在终端/命令行中运行一个 Python 脚本文件
这是最常见、最标准的用法,当你想执行一个已经写好的 Python 代码文件(my_script.py)时,你会这样做。
步骤:
- 打开终端 (在 Windows 上是 PowerShell, CMD, 或 Git Bash;在 macOS/Linux 上是 Terminal)。
- 导航到你的 Python 文件所在的目录,使用
cd命令。# 如果你的文件在桌面的 my_project 文件夹里 cd Desktop/my_project
- 使用
python命令来运行文件。python my_script.py
工作原理:

这里的第一个 python 是指令,它告诉你的操作系统:“请启动 Python 解释器程序”,第二个 my_script.py是参数,它被传递给刚刚启动的 Python 解释器,解释器会读取 my_script.py 文件中的代码,然后一行一行地执行它。
示例:
假设你有一个名为 hello.py 的文件,内容如下:
# hello.py
print("Hello from Python script!")
name = input("What's your name? ")
print(f"Nice to meet you, {name}!")
在终端中运行它:

$ python hello.py
输出:
Hello from Python script!
What's your name? Alice
Nice to meet you, Alice!
在 Python 代码中运行 Python 代码(动态执行)
这是一种更高级的用法,通常用于需要在程序运行时动态地生成并执行 Python 代码的场景,这被称为“动态执行”或“反射”。
主要有两种方式实现:
eval() 函数
eval() 函数会计算一个字符串表达式,并返回结果。
适用场景: 简单的、单行的数学或逻辑表达式。
示例:
# 定义一个字符串形式的数学表达式
expression = "10 + (5 * 3)"
# 使用 eval() 来执行这个字符串
result = eval(expression)
print(f"表达式 '{expression}' 的结果是: {result}")
输出:
表达式 '10 + (5 * 3)' 的结果是: 25
⚠️ 安全警告:
eval() 非常危险!因为它会执行字符串中的任何 Python 代码,如果字符串内容来自不可信的用户(例如网页输入框),他们可以注入恶意代码,删除你的文件等。
危险示例:
# 绝对不要对不可信的输入使用 eval()
malicious_code = "__import__('os').system('echo 你被黑了!')" # 在 Linux/macOS 上
# malicious_code = "__import__('os').system('echo 你被黑了 & pause')" # 在 Windows 上
eval(malicious_code) # 这行代码会执行系统命令!
exec() 函数
exec() 函数会执行一个字符串形式的代码块(可以包含多行语句、定义函数、类等)。
适用场景: 复杂的、多行的 Python 代码。
示例:
# 定义一个多行的 Python 代码字符串
code_block = """
def greet(name):
return f"Hello, {name}!"
# 调用这个新定义的函数
message = greet("World")
print(message)
"""
# 使用 exec() 来执行这个代码块
exec(code_block)
输出:
Hello, World!
⚠️ 安全警告:
exec() 和 eval() 一样,具有同样的安全风险,它也会执行任何传入的字符串代码,绝不能对不可信的来源使用。
总结与对比
| 特性 | python my_script.py (终端运行) |
exec() / eval() (代码中运行) |
|---|---|---|
| 目的 | 执行一个独立的、已存在的 .py 文件。 |
在程序运行时动态执行一段代码字符串。 |
| 输入 | 一个文件路径。 | 一个包含 Python 代码的字符串。 |
| 代码来源 | 程序员预先编写好的静态文件。 | 可以是程序内部生成的,也可以是用户输入的。 |
| 安全性 | 高,执行的是你自己的文件。 | 极低,如果字符串来源不可信,有严重安全风险。 |
| 常见用途 | 运行应用程序、脚本、测试等。 | 动态配置、插件系统、代码生成、数据分析中的动态表达式等。 |
如何安全地使用 exec 和 eval?
如果你确实需要动态执行代码,并且希望限制它的权限,可以使用 restrict 关键字(Python 3.8+)来创建一个受限的命名空间。
示例:
# 一个来自不可信源的代码字符串
untrusted_code = "a = 10; b = 20; print(f'计算结果: {a + b}')"
# 创建一个受限的命名空间,防止代码访问全局或本地变量
safe_namespace = {}
try:
# 将代码限制在 safe_namespace 这个“沙箱”里执行
exec(untrusted_code, safe_namespace)
print("代码执行成功。")
# 你可以从命名空间中获取变量
# print(f"沙箱中的变量 a: {safe_namespace.get('a')}") # 输出: 10
except Exception as e:
print(f"执行代码时出错: {e}")
# 尝试访问沙箱外的变量会失败
# print(safe_namespace['a']) # 可以访问
# print(a) # NameError: name 'a' is not defined
一个有趣的“在 Python 里运行 python”的例子:subprocess
你可能想在你的 Python 程序里启动一个全新的、独立的 Python 进程,这可以通过 subprocess 模块实现。
import subprocess
# 启动一个新的 Python 解释器进程,并让它执行一段代码
command = "python -c \"print('这是另一个独立的 Python 进程!'); print(2 + 2)\""
# 使用 subprocess.run 来执行命令
subprocess.run(command, shell=True)
print("主进程继续执行...")
输出:
这是另一个独立的 Python 进程!
4
主进程继续执行...
python my_script.py:这是标准的、日常的运行 Python 脚本的方式。exec()/eval():这是强大的、但危险的动态执行工具,适用于特定的高级场景,使用时必须极度小心。subprocess:用于在程序中启动一个全新的、外部的 Python 进程。
