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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 17:49:54