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

使用Snap7出现TypeError: NoneType对象不可调用问题排查求助

Snap7程序结束时触发TypeError: 'NoneType' object is not callable的根源分析与修复方案

问题情况

使用Snap7库读取PLC数据时,数据读取功能正常,但程序执行结束时会触发TypeError: 'NoneType' object is not callable错误。目前仅能通过设置snap7.client.Client.__del__ = lambda self: None跳过__del__方法临时解决,需找到问题根源及正式修复方案,以便将脚本集成到其他项目中。此前使用该库数月无异常,近期突然出现此问题。

相关代码

import snap7

plc = snap7.client.Client()
plc.connect("20.0.0.20", 0, 1)

data = plc.db_read(1, 0, 1)
x = snap7.util.get_bool(data, 0, 0)
print(x)
data = plc.db_read(1, 0, 1)
x = snap7.util.get_bool(data, 0, 1)
print(x)
data = plc.db_read(1, 0, 1)
x = snap7.util.get_bool(data, 0, 2)
print(x)
data = plc.db_read(1, 0, 1)
x = snap7.util.get_bool(data, 0, 3)
print(x)

plc.disconnect()
plc.destroy()
del plc

执行报错

True
False
True
False
Exception ignored in: <function Client.__del__ at 0x000001FD63E7EE80>
Traceback (most recent call last):
  File "C:\Users\brunosilva\AppData\Local\Programs\Python\Python312\Lib\site-packages\snap7\client.py", line 74, in __del__
  File "C:\Users\brunosilva\AppData\Local\Programs\Python\Python312\Lib\site-packages\snap7\client.py", line 92, in destroy
  File "C:\Users\brunosilva\AppData\Local\Programs\Python\Python312\Lib\logging\__init__.py", line 1538, in info
  File "C:\Users\brunosilva\AppData\Local\Programs\Python\Python312\Lib\logging\__init__.py", line 1800, in isEnabledFor
TypeError: 'NoneType' object is not callable

错误根源

从报错栈可以看出,错误发生在程序退出阶段:Client实例的__del__方法被调用时,内部执行了destroy函数,而destroy中调用了logging.info。此时Python程序已进入退出流程,全局的logging模块已被提前销毁,导致isEnabledFor方法变为None,调用时触发TypeError。

近期突然出现问题的可能原因:

  • Python版本更新(如升级到3.12),程序退出时模块销毁顺序发生变化
  • Snap7库版本更新,__del__或destroy的实现逻辑调整
  • 脚本结构变更,导致Client实例的垃圾回收时机延后到程序退出阶段

正式修复方案

方案1:使用上下文管理器(推荐)

利用Snap7 Client的上下文管理器支持,确保实例在程序正常执行阶段就完成清理,避免__del__在退出阶段被触发:

import snap7

with snap7.client.Client() as plc:
    plc.connect("20.0.0.20", 0, 1)

    data = plc.db_read(1, 0, 1)
    x = snap7.util.get_bool(data, 0, 0)
    print(x)
    data = plc.db_read(1, 0, 1)
    x = snap7.util.get_bool(data, 0, 1)
    print(x)
    data = plc.db_read(1, 0, 1)
    x = snap7.util.get_bool(data, 0, 2)
    print(x)
    data = plc.db_read(1, 0, 1)
    x = snap7.util.get_bool(data, 0, 3)
    print(x)

# with块结束后,实例自动执行close操作(包含disconnect和destroy),无需手动调用

方案2:显式控制生命周期

通过try-finally块确保实例在程序退出前完成所有清理操作,避免依赖__del__的自动调用:

import snap7

plc = snap7.client.Client()
try:
    plc.connect("20.0.0.20", 0, 1)

    data = plc.db_read(1, 0, 1)
    x = snap7.util.get_bool(data, 0, 0)
    print(x)
    data = plc.db_read(1, 0, 1)
    x = snap7.util.get_bool(data, 0, 1)
    print(x)
    data = plc.db_read(1, 0, 1)
    x = snap7.util.get_bool(data, 0, 2)
    print(x)
    data = plc.db_read(1, 0, 1)
    x = snap7.util.get_bool(data, 0, 3)
    print(x)
finally:
    plc.disconnect()
    plc.destroy()
    del plc

方案3:调整Snap7或Python版本

  • 尝试升级Snap7到最新版本:pip install --upgrade python-snap7
  • 若升级后问题仍存在,可降级到之前正常工作的Snap7版本
  • 若确认是Python版本问题,可临时降级到之前稳定的版本(如3.11)

临时方案说明

设置snap7.client.Client.__del__ = lambda self: None虽然能跳过错误,但可能导致PLC连接资源未被正确释放,长期使用存在资源泄漏风险,仅适用于临时测试,不建议在生产环境或集成项目中使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 12:31:00