如何使用 "pymqi" Python 库在我的队列管理器中配置 CCSID 值?

How can I configure CCSID value in my Queue Manager using "pymqi" Python library?

我目前正在开发一个应用程序,它需要连接一个 MQ 队列,以便在另一个服务中保存消息信息。完成后,服务 returns 通过 MQ 队列返回一条结果消息并返回给我。

我发送的字符串消息包含 XML 类似于以下消息的消息:

<?xml version="1.0" encoding="UTF-8"?>
<peticionDemanda>
<subtipo>DEMANDA CONTRATACIÓN</subtipo>
</peticionDemanda>

MQ 似乎没有正确解码“Ó”字符,"subtipo" 字段被保存为 "DEMANDA CONTRATACI├ôN"。

我在 "UTF-8" 中对消息进行编码,我被告知我用来发送消息的 CCSID 是 850 而不是 1208(属于 UTF 的-8).

对于 运行 MQ 管理器,我在客户端模式下使用 "pymqi" Python 库 。这是我用来向队列发送消息并获得响应的 MQManager class:

class MQManager:
    def __init__(self):
        self.queue_manager = config.queue_manager
        self.channel = config.channel
        self.port = config.port
        self.host = config.host
        self.conn_info = config.conn_info
        self.queue_request_name = config.queue_request_name
        self.queue_response_name = config.queue_response_name

        cd = pymqi.CD()
        cd.ChannelName = self.channel
        cd.ConnectionName = self.conn_info
        cd.ChannelType = pymqi.CMQC.MQCHT_CLNTCONN
        cd.TransportType = pymqi.CMQC.MQXPT_TCP

        self.qmgr = pymqi.QueueManager(None)
        self.qmgr.connect_with_options(self.queue_manager, opts=pymqi.CMQC.MQCNO_HANDLE_SHARE_NO_BLOCK, cd=cd)

    def send_message(self, str_xml_message):
        # set message descriptor
        request_md = pymqi.MD()
        request_md.ReplyToQ = self.queue_response_name
        request_md.Format = pymqi.CMQC.MQFMT_STRING

        queue_request = pymqi.Queue(self.qmgr, self.queue_request_name)
        queue_request.put(str_xml_message.encode("UTF-8"), request_md)
        queue_request.close()

        # Set up message descriptor for get.
        response_md = pymqi.MD()
        response_md['CorrelId'] = request_md['MsgId']

        gmo = pymqi.GMO()
        gmo.Options = pymqi.CMQC.MQGMO_WAIT | pymqi.CMQC.MQGMO_FAIL_IF_QUIESCING
        gmo.WaitInterval = 5000  # 5 seconds

        queue_response = pymqi.Queue(self.qmgr, self.queue_response_name)
        message = queue_response.get_no_rfh2(None, response_md, gmo)
        queue_response.close()

        return str(message)


    def close(self):
        self.qmgr.disconnect()

我想知道如何定义 MQ 管理器的 CCSID 值并有望解决代码页不匹配问题。

谢谢!

在您的代码中,您为在这行代码中发送的消息创建了一个默认消息描述符:

request_md = pymqi.MD()

默认情况下,pymqi(类似于底层 IBM MQ C 库)会将消息描述符 CodedCharSetId 设置为值 CMQC.MQCCSI_Q_MGR

这可以在source中看到:

['CodedCharSetId', CMQC.MQCCSI_Q_MGR, MQLONG_TYPE],

IBM MQ v9.0 KC 页面Reference > Developing applications reference > MQI applications reference > Data types used in the MQI > MQMD - Message descriptor > Fields for MQMD > CodedCharSetId (MQLONG)描述了客户端如何处理:

For client applications, MQCCSI_Q_MGR is filled in, based on the locale of the client rather than the one on the queue manager.


IBM MQ 故障排除文档 What CCSID is used by default for WebSphere MQ client messages 以稍微不同的方式对此进行了解释:

A MQ client sets the MQCCSI_Q_MGR value based on the environment in which the client application is running.


基于 850 CCSID 我猜你是 运行 在不在美国的 Windows OS 上(通常使用 CCSID 437) .


您有几个选项可以覆盖它:

  1. 您可以像这样以编程方式覆盖 pymqi MQMD 默认值:

    request_md.CodedCharSetId = 1208
    
  2. 将环境变量 MQCCSID 设置为您想要的值(在您的例子中为 1208)。这必须在连接到 mq 之前设置。这记录在 IBM MQ v9.0 KC 页面 Developing applications > Developing MQI applications with IBM MQ > Writing client procedural applications > Using the MQI in a client application > Choosing client or server CCSID.

    以下示例适用于 Windows:

    SET MQCCSID=1208
    
  3. mqclient.ini中你可以在CHANNELS节下设置CCSID=number。这记录在 IBM MQ v9.0 KC 页面 Configuring > Configuring connections between the server and client > Configuring a client using a configuration file > CHANNELS stanza of the client configuration file 中。例如:

    CHANNELS:
       CCSID=1208
    

您应该不需要更改队列管理器的 CCSID。您的问题是您的消息包含 UTF-8 字符,但您已将其放在信封中并将其描述为包含 CCSID 850 字符。您只需更新发送消息的信封即可正确描述您的内容。

我是 IBM MQ 专家和 'C' 程序员,但不是 pymqi 程序员,但是,查看 pymqi 帮助和您的示例,我希望这些是您的代码所需的补充。

# set message descriptor
request_md = pymqi.MD()
request_md.ReplyToQ = self.queue_response_name
request_md.Format = pymqi.CMQC.MQFMT_STRING
request_md.CodedCharSetId = 1208

pymqi 帮助不包含任何使用 CodedCharSetId 的示例,但似乎 MQMD 中的所有 pymqi 字段都遵循与 'C' API 头文件 cmqc.h.

请试试看是否能解决您的问题。