Python2.7下调用opcua.set_values()写入OPC UA服务器报错Bad file descriptor
OPC UA批量写入报错:[Errno 9] Bad file descriptor 解决方法
问题描述
在Python2.7环境下使用opcua库的set_values()方法向OPC UA服务器批量写入节点数据时,抛出异常:
error: [Errno 9] Bad file descriptor
异常堆栈信息:
Traceback (most recent call last): # I've marked the position in the code snippet below. File "/home/runtime/scripts/WriteToOpcTest", line 44, in TestOpcMultipleWrite opcUaClient.set_values(nodes5, values5) File "/usr/local/lib/python2.7/site-packages/opcua/client/client.py", line 672, in set_values results = self.uaclient.set_attributes(nodeids, dvs, ua.AttributeIds.Value) File "/usr/local/lib/python2.7/site-packages/opcua/client/ua_client.py", line 674, in set_attributes data = self._uasocket.send_request(request) File "/usr/local/lib/python2.7/site-packages/opcua/client/ua_client.py", line 81, in send_request future = self._send_request(request, callback, timeout, message_type) File "/usr/local/lib/python2.7/site-packages/opcua/client/ua_client.py", line 72, in _send_request self._socket.write(msg) File "/usr/local/lib/python2.7/site-packages/opcua/common/utils.py", line 118, in write self.socket.sendall(data) File "/usr/lib64/python2.7/socket.py", line 228, in meth return getattr(self._sock,name)(*args) File "/usr/lib64/python2.7/socket.py", line 174, in _dummy raise error(EBADF, 'Bad file descriptor') error: [Errno 9] Bad file descriptor
相关代码片段:
from opcua import Client from opcua import ua import Logger opcUaClient = None def InitializeOpcUa(opcUrl, username=None, password=None): global opcUaClient # Create a client object opcUaClient = Client(opcUrl) # Set user credentials if provided if username and password: opcUaClient.set_user(username) opcUaClient.set_password(password) try: # Connect to the OPC UA server opcUaClient.connect() except Exception as ex: FetchException(ex, "Error while connecting to OPC UA") def DisconnectOpcUa(): if opcUaClient is not None: opcUaClient.disconnect() def TestOpcMultipleWrite(): # Set example values values5 = [ ua.DataValue(ua.Variant(10, ua.VariantType.Int)), ua.DataValue(ua.Variant(3.14, ua.VariantType.Float)), ua.DataValue(ua.Variant("Hallo Welt", ua.VariantType.String)) ] # Set nodes nodes5 = [ opcUaClient.get_node("ns=2;i=1001"), opcUaClient.get_node("ns=2;i=1002"), opcUaClient.get_node("ns=2;i=1003") ] # Write values as batch try: opcUaClient.set_values(nodes5, values5) # I'm line 44 which is shown in TRACEBACK except Exception as ex: FetchException(ex) def FetchException(e): Logger.exception(e) # MAIN opcUrl = "opc.tcp://%s:%s" % ("localhost", str(4840)) InitializeOpcUa(opcUrl) TestOpcMultipleWrite() DisconnectOpcUa()
原因分析
该错误本质是客户端尝试使用已失效的socket连接发送数据,常见触发场景:
- 初始化连接时失败,但全局
opcUaClient变量未被重置,后续操作使用了未成功连接的客户端对象 - 服务器主动断开连接,客户端未检测到连接状态变化
- Python2.7下opcua旧版本存在socket管理兼容性bug
解决方案
1. 修复连接初始化逻辑,确保无效客户端被重置
原代码在连接失败时仅捕获异常,但未将opcUaClient置为None,导致后续操作使用无效对象。修改初始化函数:
def InitializeOpcUa(opcUrl, username=None, password=None): global opcUaClient opcUaClient = None # 先重置为None try: opcUaClient = Client(opcUrl) if username and password: opcUaClient.set_user(username) opcUaClient.set_password(password) opcUaClient.connect() except Exception as ex: FetchException(ex, "Error while connecting to OPC UA") opcUaClient = None # 连接失败后强制重置
同时在写入函数前添加有效性检查:
def TestOpcMultipleWrite(): if opcUaClient is None: FetchException(Exception("OPC UA client not initialized or connected")) return # 原有写入逻辑...
2. 写入前检查连接状态,必要时重新连接
添加连接活跃性检查,避免使用已断开的连接:
def TestOpcMultipleWrite(): global opcUaClient if opcUaClient is None: FetchException(Exception("OPC UA client not initialized")) return # 检查连接是否活跃,否则尝试重新连接 if not opcUaClient.is_connected(): try: opcUaClient.connect() except Exception as ex: FetchException(ex, "Failed to reconnect to OPC UA server") return # 原有写入逻辑...
3. 升级opcua库到Python2.7兼容的稳定版本
旧版本opcua库可能存在socket管理bug,安装Python2.7支持的最新稳定版:
pip install --upgrade opcua==0.98.13
4. 排查服务器端问题
- 确认OPC UA服务器正常运行,端口
4840可通过客户端访问 - 检查服务器是否设置了连接超时,是否在写入前已断开客户端连接
- 验证目标节点ID(如
ns=2;i=1001)存在且客户端拥有写入权限
内容的提问来源于stack exchange,提问作者explorer4x4v6
相关产品推荐
相关产品推荐

