You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python 3.7.9中importlib导入的matplotlib格式化函数报内置函数未定义错误

问题排查

尝试将通过importlib动态导入的函数作为matplotlib的坐标轴格式化器使用时,函数内部无法访问Python内置函数,运行抛出NameError,即使在格式化器代码内显式写了内置函数导入逻辑,问题也依然存在。

复现代码

formatterCode = '''
from builtins import *
def myFormatter(x, y):  
    return str(float(x))
'''

print(formatterCode,  file = open('formatter.py', 'w'))

import os, importlib
spec        = importlib.util.spec_from_file_location('module.name', 'formatter.py')
formatters  = importlib.util.module_from_spec(spec)
spec.loader.exec_module(formatters)

import matplotlib, dill
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
myFormatter = matplotlib.ticker.FuncFormatter(formatters.myFormatter)
ax.yaxis.set_major_formatter(myFormatter)
ax.plot([1, 2], [1, 2])
with open('test.tmp', 'wb') as f:
    dill.dump(fig, f, recurse = False)

plt.close('all')

with open('test.tmp', 'rb') as f:
    figure = dill.load(f)

figure.savefig("test.png")
plt.close('all')

运行环境

Python 3.7.9 (default, Feb 18 2021, 03:10:35)
[GCC 7.3.1 20180712 (Red Hat 7.3.1-12)] on linux

报错信息

File "formatter.py", line 4, in myFormatter
    return str(float(x))
NameError: name 'str' is not defined

问题成因

  • 用importlib从指定路径动态加载模块时,默认不会把模块注册到全局sys.modules索引表中,后续序列化、反序列化全流程根本定位不到模块的原始全局命名空间
  • 序列化时传入的*recurse = False参数*会让dill跳过对函数关联依赖的递归序列化,不会把函数引用的模块全局变量、内置函数绑定关系持久化,只保留函数本身的代码文本引用
  • 格式化器代码里写的from builtins import *,反而把原本Python解释器自动给每个函数绑定的内置函数引用,变成了模块全局作用域里的普通变量。一旦模块引用在序列化时丢失,这些绑定的普通变量就会彻底消失,自然触发找不到str、float这类内置函数的NameError

修复方案

  • 动态模块加载完成后,显式将模块注册到sys.modules,保证序列化反序列化时能准确定位到模块全局命名空间:
import sys
# 模块加载完成后追加这行代码
sys.modules[spec.name] = formatters
  • 移除dill序列化时的recurse = False参数,让序列化流程正常保留函数的全局作用域绑定关系,不要跳过依赖递归
  • 删除格式化器代码里的from builtins import *逻辑,Python解释器会自动给每个函数关联对应模块的内置函数表,不需要手动导入内置名

内容的提问来源于stack exchange,提问作者user3876608

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.27 02:45:02