Python技术迷

如何安全运行别人上传的Python代码?

在日常开发里啊,最让人头疼的一类需求就是——别人上传了一段 Python 代码让你跑,这种场景不少见,比如在线判题系统、数据分析平台,甚至团队里做 demo 的时候也会遇到。但问题也来了:你敢直接 exec 吗?十有八九就变成“帮别人挖坑自己跳”了。下面就聊聊几个比较靠谱的思路。

为什么不能直接跑?

想象下,有人上传这么一段代码:

import os
os.remove("/etc/passwd")

如果你在服务器上直接跑,数据就废了。更糟糕的是,它还能开网络连接、疯狂占 CPU 内存,甚至 fork 炸掉你的机器。所以第一条原则:永远不要直接运行。

用沙盒隔离

最常见的方法就是搞个沙盒环境。比如用 Docker 容器 或 虚拟机,把上传的代码限制在一个“盒子”里跑,出了问题也不会伤到宿主机。

简单示例(假设你用 Python 调用 Docker):

import docker

client = docker.from_env()
container = client.containers.run(
"python:3.9", 
"python -c 'print(1+1)'",
    detach=True,
    network_disabled=True,
    mem_limit="128m",
    cpu_quota=50000
)
print(container.logs().decode())

这里做了几件事:禁用网络、限制内存 128M、限制 CPU,保证代码不会乱跑。

控制可用的模块

就算在沙盒里,也要限制能用的库。不然有人上传 subprocess.Popen("rm -rf /"),一样危险。可以通过在执行环境里只保留安全的内置函数,比如这样:

safe_globals = {"__builtins__": {"print": print, "range": range}}
code = "for i in range(5): print(i)"
exec(code, safe_globals)

这里我们手动指定了能用的函数,其他的比如 open、os 就访问不到了。

超时和资源控制

除了 Docker 这种“硬隔离”,你也可以在本地用 资源限制。Linux 下有个 resource 模块,可以限制 CPU 时间、内存使用,比如:

import resource, signal

deflimit_resources():
    resource.setrlimit(resource.RLIMIT_CPU, (1, 1))      # 最多 1 秒 CPU
    resource.setrlimit(resource.RLIMIT_AS, (100*1024*1024, 100*1024*1024))  # 100MB 内存

defhandler(signum, frame):
raise TimeoutError("Time limit exceeded")

signal.signal(signal.SIGXCPU, handler)
limit_resources()

exec("while True: pass")  # 会被强制杀掉

这样就算有人写死循环,也撑不了多久。

更高级的玩法

如果你做的是对外服务,最好是多层防护:

  1. 容器隔离(Docker/K8s)
  2. 系统层 cgroup 限制(CPU/内存/文件数)
  3. 语言层安全沙盒(过滤内置函数)
  4. 超时机制(防死循环)

这几层叠加起来,基本就能保证别人上传的代码不会把你的服务拖垮。

总之,安全运行别人的 Python 代码,其实就是“不给它机会捣乱”。容器是最通用的方案,配合 Python 自带的 resource、信号超时、白名单函数,就能做到可控可用。

-END-

我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html

🔥虎哥私藏精品🔥

虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB,点击下方公众号回复关键字 python 全部免费领