概述
在IBM developerWorks的上一篇文章中,我写了关于使用Python创建命令行工具的乐趣。 本文通过创建插件来扩展命令行工具,将命令行工具提升到了一个新的高度。 插件和命令行工具都提供了方便的方法来扩展现有代码的功能。 一起使用,它们可以成为非常强大的工具。
为了开始编写插件,您将使用我编写的名为pathtool的开源Python软件包,该软件包使用生成器遍历文件系统并产生文件对象。 专门编写该库是为了允许开发人员通过编写自己的对文件对象起作用的过滤器来扩展它,然后返回结果。
实际的Python模块代码比您希望看到的文章要大一些,因此,我将仅发布您将实际使用的API的摘要:
清单1. pathtool API
def path(fullpath, pattern="*", action=(lambda rec: print_rec(rec))):
"""This takes a path, a shell pattern, and an action callback
This function uses the slower pathattr function which calculates checksums
"""
for rec in pathattr(fullpath):
for new_record in match(pattern, rec):
#applies filter
action(new_record)
#Applies lambda callback to generator object
查看此示例,您可以知道path函数采用强制性的path-positional参数以及可选的pattern关键字参数和称为lambda回调的可选action关键字参数。 路径的默认回调仅打印出文件名作为示例。 开发人员只需要easy_install pathtool。 有关使用easy_install命令的信息,请参见参考资料部分 ,然后导入模块并按如下所示调用函数:
from pathtool import path
path("/tmp", pattern="*.mp3", action=(lambda rec: print_rec(rec)))
注意:为了方便起见,我在本文中包含了pathtool的源代码 。 需要指出的一件事是lambda的使用。 您可以在参考资料小节中阅读有关它们的Python教程条目的链接,但总而言之,lambda是告诉函数“调用”另一个函数的便捷方法。
编写可插拔命令行工具
现在,我们对如何使用包含回调的路径遍历库有了一个大致的了解,是时候该开始实际编写可使用插件扩展的命令行工具了。 首先查看完成的版本,然后将其分解为较小的部分:
清单2.带有插件的命令行工具
#!/usr/bin/env python
# encoding: utf-8
"""
pathtool-cli.py 0.1
A commandline tool for walking a filesystem.
Takes Action callback plugins in a plugin directory
action=(lambda rec: print_rec(rec))
"""
from pathtool import path
import optparse
import re
import os
import sys
try:
plugin_available = True
from plugin import *
from plugin import __all__ #note this is the registered plugin list
except ImportError:
plugin_available = False
def path_controller():
descriptionMessage = """
A command line tool for walking a filesystem.
Takes callback 'Action' functions as plugins.
example: pathtool_cli /tmp print_path_ext
"""
p = optparse.OptionParser(description=descriptionMessage,
prog='pathtool',
version='pathtool 0.1.1',
usage= '%prog [starting directory][action]')
p.add_option('--pattern', '-p',
help='Pattern Match Examples: *.txt, *.iso, music[0-5].mp3
plain number defaults to * or match all.
Uses UNIX standard wildcard syntax.',
default='*')
p.add_option('--list', '-l',
action="store_true",
help='lists available action plugins',
default=False)
options, arguments = p.parse_args()
if options.list:
try:
print "Action Plugins Available:"
if plugin_available:
for p in __all__:
print p
finally:
sys.exit(0)
if len(arguments) == 2:
fullpath = arguments[0]
try:
action_plugin = eval(arguments[1])
#note we expect the plugin author to write a method with our naming convention
#path(fullpath,options.pattern,action=(lambda rec: move_to_tmp.plugin(rec)))
path(fullpath, options.pattern,action=(lambda rec: action_plugin.plugin(rec)))
except NameError:
sys.stderr.write("Plugin Not Found")
sys.exit(1)
else:
print p.print_help()
def main():
path_controller()
if __name__ == '__main__':
main()
运行此示例将得到以下输出:
# python pathtool_cli.py
Usage: pathtool [starting directory][action]
A command line tool for walking a filesystem.
Takes callback 'Action'
functions as plugins.
example: pathtool_cli /tmp print_path_ext
Options:
--version
show program's version number and exit
-h, --help
show this help message and exit
-p PATTERN, --pattern=PATTERN
Pattern Match Examples: *.txt, *.iso, music[0-5].mp3
plain number defaults to * or match all.
Uses UNIX standard wildcard syntax.
-l, --list
lists available action plugins
从命令的输出中,您可以看到该工具期望采取完整路径,然后采取“行动”。 该操作是开发人员创建的插件。 我添加了一个命令行选项列表,该列表允许命令行工具的用户查看可用的插件。 看一下这个输出:
# python pathtool_cli.py -l
Action Plugins Available:
move_to_tmp
print_file_path_ext
无需过多了解该工具的工作原理,某人可能会猜出某个动作的名称。 因为我编写的print_file_path_ext操作仅打印文件,路径,ext,所以继续运行并查看其外观:
# python pathtool_cli.py /tmp print_file_path_ext
/tmp/foo0.txt | foo0.txt | .txt
/tmp/foo1.txt | foo1.txt | .txt
/tmp/foo10.txt | foo10.txt | .txt
/tmp/foo2.txt | foo2.txt | .txt
/tmp/foo3.txt | foo3.txt | .txt
/tmp/foo4.txt | foo4.txt | .txt
/tmp/foo5.txt | foo5.txt | .txt
/tmp/foo6.txt | foo6.txt | .txt
/tmp/foo7.txt | foo7.txt | .txt
/tmp/foo8.txt | foo8.txt | .txt
/tmp/foo9.txt | foo9.txt | .txt
我之前使用touch foo{0..10}.txt
创建了十个临时文件,现在命令行工具使用了一个插件,该插件可以打印出全路径,文件名和扩展名,并以“ |” 字符。
简单的插件架构说明
到目前为止,我一直希望您信任我,而无需告诉您这些“神奇的”插件操作来自何处。 首先要看的是模块顶部的import语句。 尝试以下方法:
plugin_available = True
from plugin import *
from plugin import __all__ #note this is the registered plugin list
except ImportError:
plugin_available = False
此import语句将令人惊奇的简单插件体系结构的秘密透露了出来。 Python官方文档通常不鼓励使用语法“ from package import *”,但是如果有充分的理由(例如编写插件),则插件作者负责在__init__中创建条目。位于插件目录中的.py文件。 它看起来应该像这样:
"""Lists all of the importable plugins"""
__all__ = ["move_to_tmp", "print_file_path_ext"]
通过设置此选项,它允许将包或目录中的所有模块导入为*。 接下来,我导入实际的__all__列表,以用作向用户显示可用插件的方式。 最后,还有一点点魔术。 因为命令行工具直到运行时才知道要使用什么插件操作,所以请使用eval将命令行上的操作字符串转换为可调用函数。 这是魔术路线:
action_plugin = eval(arguments[1])
通常,在使用eval时应格外小心,但在这种情况下,可以合理地告诉我们的工具使用插件方法。
看一下插件
现在您已经了解了插件体系结构应该如何工作,现在来看一个实际的插件。 请注意,为了使该体系结构起作用,在当前工作目录或Python site-packages目录中需要有一个插件目录。 这个特定的插件称为print_file_path_ext.py,它具有一种称为插件的方法。 这是插件开发人员必须符合的预期API:
清单3.示例插件
#!/usr/bin/env python
# encoding: utf-8
"""
prints path, name, ext, plugin
"""
def plugin(rec, verbose=True):
"""Moves matched files to tmp directory"""
path = rec["path"]
filename = rec["filename"]
ext = rec["ext"]
print "%s | %s | %s" % (path, filename, ext)
该插件是一个非常简单的功能,但是它使用rec参数,该参数是pathtool模块生成的字典。 该词典包含以下API:
{"path": path, "filename": file, "ext": ext, "size": size,
"unique_id": unique_id, "mtime": mtime, "ctime": ctime}
在此示例中,每次调用该特定文件对象时,我都使用字典的键来打印该文件对象的值。 插件作者可以编写许多其他有用的动作,这些动作可以转换文件,重命名文件,归档文件等。
摘要
本文演示了一个相当简单的插件体系结构,它是扩展Python中命令行工具的有用方法。 但是,有些事情要注意。 首先,参考文献中包含了easy_install提供的更复杂的插件系统。 该插件系统允许用户创建“入口点”,这些入口点定义了特定工具的插件。 其次,我们的命令行工具的编写方式仅允许使用一个“动作”插件。 我将把它留给读者作为练习来修改命令行工具,使它可以收到无限数量的“可链接”回调动作的练习。
创建可链接插件的一个潜在陷阱是,设计必须考虑其使用的API的性质。 在我们的案例中,我们建立在可产生收益的发电机的基础上。 为了使我们的工具继续将插件“链接”在一起,它们必须完成工作,但仍要返回字典记录。 我希望本文能激发您编写自己的命令行工具插件。
翻译自: https://www.ibm.com/developerworks/aix/library/au-cli_plugins/index.html
最后
以上就是健康哑铃为你收集整理的python编写ocx插件_用Python编写插件的全部内容,希望文章能够帮你解决python编写ocx插件_用Python编写插件所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复