自从我第一次问自己几乎同样的问题以来,至少已经5年了,现在你的问题是一个终于找到它的冲动.
对于我来说,如果可以在不安装软件包的情况下从与脚本相同的目录中添加入口点,那么这很有趣.虽然我总是知道包的唯一内容可能是一些元素,入口点查看其他一些包.
无论如何,这里是我的目录的一些设置:
ep_test newtover$tree
.
├── foo-0.1.0.dist-info
│ ├── METADATA
│ └── entry_points.txt
└── foo.py
1 directory, 3 files
这是foo.py的内容:
ep_test newtover$cat foo.py
def foo1():
print 'foo1'
def foo2():
print 'foo2'
现在我们来打开ipython:
In [1]: def write_ep(lines): # a helper to update entry points file
...: with open('foo-0.1.0.dist-info/entry_points.txt', 'w') as f1:
...: print >> f1, '\n'.join(lines)
...:
In [2]: write_ep([ # only one entry point under foo.test
...: "[foo.test]",
...: "foo_1 = foo:foo1",
...: ])
In [3]: !cat foo-0.1.0.dist-info/entry_points.txt
[foo.test]
foo1 = foo:foo1
In [4]: import pkg_resources
In [5]: ws = pkg_resources.WorkingSet() # here is the answer on the question
In [6]: list(ws.iter_entry_points('foo.test'))
Out[6]: [EntryPoint.parse('foo_1 = foo:foo1')]
In [7]: write_ep([ # two entry points
...: "[foo.test]",
...: "foo_1 = foo:foo1",
...: "foo_2 = foo:foo2"
...: ])
In [8]: ws = pkg_resources.WorkingSet() # a new instance of WorkingSet
使用默认参数WorkingSet只是重新访问sys.path中的每个条目,但您可以缩小列表. pkg_resources.iter_entry_points绑定到WorkingSet的全局实例.
In [9]: list(ws.iter_entry_points('foo.test')) # both are visible
Out[9]: [EntryPoint.parse('foo_1 = foo:foo1'), EntryPoint.parse('foo_2 = foo:foo2')]
In [10]: foos = [ep.load() for ep in ws.iter_entry_points('foo.test')]
In [11]: for func in foos: print 'name is {}'.format(func.__name__); func()
name is foo1
foo1
name is foo2
foo2
还有METADATA的内容:
ep_test newtover$cat foo-0.1.0.dist-info/METADATA
Metadata-Version: 1.2
Name: foo
Version: 0.1.0
Summary: entry point test
UPD1:我再次想到了,现在明白,在使用新插件之前,您需要一个额外的步骤:您需要重新加载模块.
这可能很简单:
In [33]: modules_to_reload = {ep1.module_name for ep1 in ws.iter_entry_points('foo.test')}
In [34]: for module_name in modules_to_reload:
....: reload(__import__(module_name))
....:
但是,如果新版本的插件包基于其他已使用模块的重大更改,则可能需要重新加载和重新加载这些更改的模块的特定顺序.这可能是一个麻烦的任务,所以重新启动机器人将是唯一的途径.