在WebSphere MQ应用程序中使用Python

    技术2022-07-21  72

    Python MQ接口

    Python MQ接口(PyMQI)是IBM®WebSphere®MQ的开源Python扩展库。 PyMQI通过提供易于使用的Python界面扩展了MQI库。 ,它包括一个用C编写的用于访问MQI C库的低级库,以及一个位于低级库之上的,面向Python程序员的高级面向对象的接口。 PyMQI使开发人员可以在WebSphere MQ工具和解决方案中使用强大的Python语言,从而为所有WebSphere MQ开发人员提供Python的好处。 Python主页上的一句话引述了这一点:

    “ Python是一种动态的面向对象的编程语言...带有大量的标准库,并且可以在几天之内学会...程序员报告了可观的生产率提高...该语言鼓励开发更高质量,更易维护的代码”。

    编译PyMQI

    PyMQI是作为源分发的,因此在将包下载并解压缩到目录后,您需要做的第一件事就是对其进行编译。 通常,Python扩展使用与Python本身相同的编译器进行编译。 Python发行版是使用Microsoft®Visual Studio构建的,如果安装了正确的版本,则可以使用命令python setup.py build server (对于WebSphere MQ Server V5)或python setup.py build client (对于WebSphere MQ Client)来构建PyMQI。 V5)

    如果您没有Microsoft Visual Studio并且使用的是WebSphere MQ V6,则在使用PyMQI之前,编译需要其他步骤:

    为Windows®C编译器安装MinGW32(极简GNU)。 修改WebSphere MQ C头文件。 编译PyMQI。 安装PyMQI作为Python扩展。

    编译要求在您的计算机中安装Windows,Python V2.5.1和WebSphere MQ V5或V6 Server或Client。 对于本文,环境包括Windows XP 2003,WebSphere MQ V6 Server和Python V2.5.1。

    安装MinGW32

    下载MinGW-5.1.3.exe并执行以开始安装。 安装程序会从Web下载所需的软件包并进行安装。 完整安装会安装所有编译器,尽管最低安装可能就足够了。 安装MinGW之后,将MinGW \ bin目录添加到PATH环境变量中。

    修改WebSphere MQ C头文件

    如果使用的是WebSphere MQ V6,则需要对MQ C头文件进行一些小的更改,因为MinGW无法理解几个64位类型定义。

    在文本编辑器中打开头文件<MQ_INSTALL_DIR>\Tools\c\include\cmgc.h ,然后找到清单1中的代码:

    清单1.要替换的Typedef
    typedef _int64 MQINT64; typedef unsigned _int64 MQUINT64;

    删除或注释掉清单1中的typedef。 然后添加清单2中所示的新的typedef,并保存文件。

    清单2.要替换的Typedef
    typedef long long _int64; typedef unsigned long long _uint64; typedef _int64 MQINT64; typedef _uint64 MQUINT64;

    编译PyMQI

    在提取PyMQI源文件的目录中打开命令提示符,并使用命令setup.py build -cmingw32 server编译PyMQI。 该命令编译PyMQI扩展,以准备将其安装为Python扩展。

    将PyMQI安装为Python扩展

    要将PyMQI安装为Python扩展,请使用命令setup.py install --skip-build 。 PyMQI现在已安装并可以使用。

    用PyMQI编程

    PyMQI具有多个一起使用的模块:

    CMQC和CMQCFC定义MQI常数。 pymqe是用C编写的MQI的低级Python扩展接口。 pymqi是使用pymqe的MQ的高级Python接口。

    实际上,在开发WebSphere MQ应用程序时使用pymqi。 清单3显示了将消息放入队列的最少代码:

    清单3.将消息放入队列
    import pymqi qmgr = pymqi.QueueManager() putQ = pymqi.Queue(qmgr, 'QNAME') putQ.put('Hello world!')

    从队列中获取消息也很简单:

    清单4.从队列获取消息
    import pymqi qmgr = pymqi.QueueManager() getQ = pymqi.Queue(qmgr, 'QNAME') print 'Message:', getQ.get()

    PyMQI支持主要的MQI调用,例如MQCONN/MQCONNX, MQDISC, MQOPEN, MQCLOSE, MQPUT, MQGET,等。 PCF命令以及事务也受支持。

    下一部分包括一些用PyMQI编写的有用工具:PyPut,PyGet和PyBrowse。 在执行任何程序之前,将创建一个名为TEST_QM的WebSphere MQ队列管理器和一个名为TESTQ的本地队列。

    PyMQI实用程序

    本节包含PyMQI的示例,并为WebSphere MQ开发人员和管理员提供有用的工具。 PyPut是一种将一个或多个消息(指定为参数或文件)放入队列的工具。 PyGet从队列中获取消息,并将其打印到系统中,或者一次发送一个消息,或一次将所有消息保存到文件中。 PyBrowse浏览消息-它也可以浏览队列中的特定消息或以后进先出(LIFO)顺序浏览消息,而不是常规的先进先出(FIFO)顺序。

    您可以下载示例代码并按原样使用-只需将代码复制并粘贴到文件中并执行即可。

    PyPut

    清单5包含PyPut的代码。 除了pymqi,PyPut还使用Python模块OptionParser定义命令行选项:

    清单5. PyPut.py
    from pymqi import * import sys, os from optparse import OptionParser usage='Usage: %s [options] QMGRNAME QNAME (MSSG | FILE_NAME) [(MSG | FILE_NAME)...]' def main(argv=None): if argv is None: argv = sys.argv try: (options,args)=parseOptions() if len(args)<3: raise MQException(1) qmgrName=args[0] qName=args[1] message=args[2] messages=args[2:] #open queue in specified queue manager qmgr = QueueManager(qmgrName) putQ = Queue(qmgr, qName) #loop through arguments and put messages #to a queue for message in messages: #if -f options is specified, arguments are file names if options.msgIsFile==True: if os.path.exists(message)==False: raise MQException(3) #read file contents to a message-variable f=open(message) content=f.readlines() f.close() #variable 'content' is a list of lines in the specified file #join lines in content-variable together as one string message=''.join(content) #single method call to put message to a queue putQ.put(message) if not options.quiet==True: print 'Message sent.' except MQException, err: #if exception happens, print error message and exit print '[ERROR]',err.errorCodes[err.msg] print usage % (sys.argv[0],) return err.code except MQMIError,err: print err return -1 def parseOptions(): parser = OptionParser(usage=(usage % ('%prog',))) parser.add_option("-f", "--file", action="store_true", dest="msgIsFile", help="Use file specified as third argument as message .", ) parser.add_option("-q", "--quiet", action="store_true", dest="quiet", help="Quiet mode.", ) (options, args) = parser.parse_args() return (options, args) #MQException class that holds application specific error codes #and error messages class MQException(Exception): errorCodes={'1': 'QMGRNAME, QNAME or MESSAGE missing.', '2': 'Too many arguments.', '3': 'File does not exist.', '4': 'QMGRNAME or QNAME.', } code=0 def __init__(self, code): self.code=code self.msg = str(code) if __name__ == "__main__": sys.exit(main())

    上面清单5中的代码主要是应用程序逻辑,实际的PyMQI代码只有几行:获取队列管理器,获取队列,将消息放入队列以及错误处理。 这显示了PyMQI的强大功能:在Python程序中使用WebSphere MQ是微不足道的,Python的内置功能使开发工具非常容易。 例如,读取文件内容是四行代码,并且可能是您自己的工具箱中的函数。 Python OptionParser模块中有-h和-help选项,以打印命令行帮助。 例如, PyPut.py -h可帮助PyPut:

    Usage: PyPut.py [options] QMGRNAME QNAME (MSSG | FILE_NAME) [(MSG | FILE_NAME)...] Options: -h, --help show this help message and exit -f, --file Use file specified as third argument as message . -q, --quiet Quiet mode.

    使用命令PyPut.py TEST_QM TESTQ message1 message2 。 此命令将两个消息放入队列管理器TEST_QM中名为TESTQ的队列。

    PyPut.py也可以在脚本中使用。 例如: @for %i in ("*.txt") do call "PyPut.py" "-f" "TEST_QM" "TESTQ" "%i"循环当前目录中的所有txt文件,并将每个目录的内容放入txt文件放入队列。

    PyGet

    PyGet.py与PyPut.py相似,除了消息被打印到系统输出或写入文件外。 清单6显示了PyGet.py的代码:

    清单6. PyGet.py
    from pymqi import * import sys, os from optparse import OptionParser usage='Usage: %s [options] QMGRNAME QNAME' def main(argv=None): if argv is None: argv = sys.argv try: (options,args)=parseOptions() if len(args)>2: raise MQException(2) if len(args)<2: raise MQException(4) qmgrName=args[0] qName=args[1] #open queue manager and queue qmgr = QueueManager(qmgrName) Q = Queue(qmgr, qName) if options.all==True: moreMessages=True while(moreMessages): try: #get single message from queue message=Q.get() printMessage(options,message) except MQMIError,err: if err.reason==2033: moreMessages=False if not options.quiet==True: if not options.noDelim==True: print '-'*70 print 'No messages.' else: raise else: message=Q.get() printMessage(options,message) except MQException, err: print '[ERROR]',err.errorCodes[err.msg] print usage % (sys.argv[0],) return err.code except MQMIError,err: if err.reason==2033: #no messages if not options.quiet==True: print 'No messages.' else: print err return err.reason def printMessage(options,message): if options.saveFile==True: seq=1 if not options.fileName==None: fileName=options.fileName else: fileName='message' fileName='%sd' %(fileName,seq) while os.path.exists(fileName)==True: fileName=fileName[:-5] seq=seq+1 fileName='%sd' %(fileName,seq) f=open(fileName,'w') f.write(message) f.close() else: if not options.quiet==True: if not options.noDelim==True: print '-'*70 print message def parseOptions(): parser = OptionParser(usage=(usage % ('%prog',))) parser.add_option("-f", "--file", action="store_true", dest="saveFile", help="Save message to a file with name 'message'.", ) parser.add_option("-n", "--file-name", dest="fileName", help="File name for message. Use with -f option.", ) parser.add_option("-A", "--all", action="store_true", dest="all", help="Get all messages. If messages are saved to file,"+ " messages have sequence number in the file name.", ) parser.add_option("-q", "--quiet", action="store_true", dest="quiet", help="Quiet mode.", ) parser.add_option("", "--no-delim", action="store_true", dest="noDelim", help="Do not print message delimeter.", ) (options, args) = parser.parse_args() return (options, args) #MQException class that holds application specific error codes #and error messages class MQException(Exception): errorCodes={'1': 'QMGRNAME, QNAME or MESSAGE missing.', '2': 'Too many arguments.', '3': 'File does not exist.', '4': 'QMGRNAME or QNAME missing.', } code=0 def __init__(self, code): self.code=code self.msg = str(code) if __name__ == "__main__": sys.exit(main())

    就像在PyPut.py中一样,实际的WebSphere MQ特定代码只有几行,而应用程序逻辑则使用了大多数源代码。 要获得有关PyGet的帮助,请键入PyPut.py -h :

    Usage: PyGet.py [options] QMGRNAME QNAME Options: -h, --help show this help message and exit -f, --file Save message to a file with name 'message'. -n FILENAME, --file-name=FILENAME File name for message. Use with -f option. -A, --all Get all messages. If messages are saved to file, messages have sequence number in the file name. -q, --quiet Quiet mode. --no-delim Do not print message delimeter.

    PyGet.py可以使用几个选项。 如果没有选项,它将从队列中检索一条消息并将其打印到系统中。 使用-A选项,将从队列中检索所有消息,这对于清除队列很有用,在开发过程中您可能需要经常这样做。 例如: PyGet.py -A -q TEST_QM TESTQ清除TESTQ而不打印任何内容到系统中。 当脚本中包含此命令时,单个命令将清除队列。

    Py浏览

    PyBrowse.py具有与PyGet.py类似的功能,但是它浏览消息并且没有静默模式。 其他选项是--index, --lifo, --depth 。 index选项浏览指定索引中的消息-索引0是第一条消息,索引1是第二条消息,依此类推。 lifo选项在将消息打印到系统之前,先反转队列中的消息,并且可用于浏览放入队列中的最后一条消息。 depth选项使用inquery函数返回队列的当前深度。

    PyBrowse的源代码:

    清单7. PyBrowse.py
    from pymqi import * import sys, os from optparse import OptionParser usage='Usage: %s [options] QMGRNAME QNAME' def main(argv=None): if argv is None: argv = sys.argv try: (options,args)=parseOptions() if len(args)>2: raise MQException(2) if len(args)<2: raise MQException(4) qmgrName=args[0] qName=args[1] #open queue manager qmgr = QueueManager(qmgrName) gqdesc = od( ObjectName=qName) Q= Queue( qmgr, gqdesc) qDepth=Q.inquire(CMQC.MQIA_CURRENT_Q_DEPTH) if options.depth==True: #open queue for inquire print 'Current depth: %d' % qDepth return 0 if not options.index==None: if int(options.index)>=qDepth: raise MQException(5) #open queue for browsing Q= Queue( qmgr, gqdesc, CMQC.MQOO_BROWSE) msgDesc = md() getOpts = gmo(Options = CMQC.MQGMO_BROWSE_NEXT) getOpts.WaitInterval = CMQC.MQWI_UNLIMITED messages = [] try: while 1: msg = Q.get(None, msgDesc, getOpts) messages.append(msg) if not options.all==True and options.index==None and not options.lifo==True: break # null MsgId and CorrelId, or cursor won't move up # the Q msgDesc['MsgId'] = '' msgDesc['CorrelId'] = '' except MQMIError, me: #assume that error is raised when there are #no more messages in queue pass if options.lifo==True: messages.reverse() if not options.all==True and options.index==None: messages=messages[0:1] if not options.index==None: printMessage(options,messages[int(options.index)]) else: for message in messages: printMessage(options,message) except MQException, err: print '[ERROR]',err.errorCodes[err.msg] print usage % (sys.argv[0],) return err.code except MQMIError,err: if err.reason==2033: #no messages print 'No messages.' else: print err return err.reason def printMessage(options,message): if options.saveFile==True: seq=1 if not options.fileName==None: fileName=options.fileName else: fileName='message' fileName='%sd' %(fileName,seq) while os.path.exists(fileName)==True: fileName=fileName[:-5] seq=seq+1 fileName='%sd' %(fileName,seq) f=open(fileName,'w') f.write(message) f.close() else: if not options.noDelim==True: print '-'*70 print message def parseOptions(): parser = OptionParser(usage=(usage % ('%prog',))) parser.add_option("-f", "--file", action="store_true", dest="saveFile", help="Save message to a file with name 'message'.", ) parser.add_option("-n", "--file-name", dest="fileName", help="File name for message. Use with -f option.", ) parser.add_option("-i", "--index", dest="index", help="Browse message in the middle of queue.", ) parser.add_option("-A", "--all", action="store_true", dest="all", help="Browse all messages. If messages are saved to file,"+ " messages have sequence number in the file name.", ) parser.add_option("-d", "--depth", action="store_true", dest="depth", help="Print just the queue depth.", ) parser.add_option("-l", "--lifo", action="store_true", dest="lifo", help="Print last message first (Last-In-First-Out).", ) parser.add_option("", "--no-delim", action="store_true", dest="noDelim", help="Do not print message delimeter.", ) (options, args) = parser.parse_args() return (options, args) #MQException class that holds application specific error codes #and error messages class MQException(Exception): errorCodes={'1': 'QMGRNAME, QNAME or MESSAGE missing.', '2': 'Too many arguments.', '3': 'File does not exist.', '4': 'QMGRNAME or QNAME missing.', '5': 'Index error. Not so many messages in queue.', } code=0 def __init__(self, code): self.code=code self.msg = str(code) if __name__ == "__main__": sys.exit(main())

    PyBrowse的帮助:

    Usage: PyBrowse.py [options] QMGRNAME QNAME Options: -h, --help show this help message and exit -f, --file Save message to a file with name 'message'. -n FILENAME, --file-name=FILENAME File name for message. Use with -f option. -i INDEX, --index=INDEX Browse message in the middle of queue. -A, --all Browse all messages. If messages are saved to file, messages have sequence number in the file name. -d, --depth Print just the queue depth. -l, --lifo Print last message first (Last-In-First-Out). --no-delim Do not print message delimeter.

    构建可执行文件

    在某些情况下,您的工具的用户将不会安装Python,因此拥有可执行文件进行分发非常有用。 幸运的是,使用Python和py2exe扩展名可以轻松地将Python脚本转换为Windows可执行文件,并且py2exe在单个目录中包含所有必需的Python文件,这些文件可以分发给用户。 要创建Python脚本的可执行文件,请先安装py2exe,然后创建安装脚本。 清单8具有用于Python MQ工具的最小安装脚本:

    清单8. setup.py
    from distutils.core import setup import py2exe setup( console = ["PyPut.py"], ) setup( console = ["PyGet.py"], ) setup( console = ["PyBrowse.py"], )

    在Python MQ脚本所在的目录中执行setup.py。 使用命令python setup.py py2exe并等待其完成。 现在,您有一个dist目录,其中包含Python MQ脚本作为可执行文件以及执行PyMQ工具所需的所有文件。 如果您在dist目录中查找,则会看到py2exe包含了所有必需的WebSphere MQ dll文件。 要将脚本分发给未安装WebSphere MQ的用户(例如,如果您的工具是远程管理工具),则可以将其保留在那里-否则,您应从dist目录中删除除python25.dll以外的所有dll文件。 脚本将从系统路径中找到MQ dll文件。

    摘要

    借助Python MQ接口,您可以使用Python语言为WebSphere MQ开发实用程序。 因为Python是用于快速开发的强大工具,所以PyMQI将快速开发扩展到WebSphere MQ程序。 在投入生产之前,可以使用Python快速测试和验证解决方案。 本文中描述的工具是示例,可以在开发使用WebSphere MQ的解决方案时在日常工作中使用。 由于使用了Python和PyMQI,示例代码会随着时间的推移而发展,并且这些示例可以成为开发人员或管理员工具箱中的资产。


    翻译自: https://www.ibm.com/developerworks/websphere/library/techarticles/0708_salkosuo/0708_salkosuo.html

    相关资源:jdk-8u281-windows-x64.exe
    Processed: 0.014, SQL: 9