|
1 | 1 | # 跨插件访问 |
| 2 | + |
| 3 | +由于 `nonebot2` 独特的插件加载机制,在使用 python 原有的 import 机制来进行插件之间的访问时,很可能会有奇怪的或者意料以外的情况发生。为了避免这种情况的发生,您可以有两种方法来实现跨插件访问: |
| 4 | + |
| 5 | +1. 将插件间的要使用的公共代码剥离出来,作为公共文件或者文件夹,提供给插件加以调用。 |
| 6 | +2. 使用 `nonebot2` 提供的 `export` 和 `require` 机制,来实现插件间的互相调用。 |
| 7 | + |
| 8 | +第一种方法比较容易理解和实现,这里不再赘述,但需要注意的是,请不要将公共文件或者公共文件夹作为**插件**被 `nonebot2` 加载。 |
| 9 | + |
| 10 | +下面将介绍第二种方法—— `export` 和 `require` 机制: |
| 11 | + |
| 12 | +## 使用 export and require |
| 13 | + |
| 14 | +现在,假定有两个插件 `pluginA` 和 `pluginB`,需要在 `pluginB` 中调用 `pluginA` 中的一个变量 `varA` 和一个函数 `funcA`。 |
| 15 | + |
| 16 | +在上面的条件中涉及到了两种操作:一种是在 `pluginA` 的 `导出对象` 操作;而另一种是在 `pluginB` 的 `导入对象` 操作。在 `nonebot2` 中,`导出对象` 的操作用 `export` 机制来实现,`导入对象` 的操作用 `require` 机制来实现。下面,我们将逐一进行介绍。 |
| 17 | + |
| 18 | +:::warning 警告 |
| 19 | + |
| 20 | +使用这个方法进行跨插件访问时,**需要先加载`导出对象`的插件,再加载`导入对象`的插件。** |
| 21 | + |
| 22 | +::: |
| 23 | + |
| 24 | +### 使用 export |
| 25 | + |
| 26 | +在 `pluginA` 中,我们调用 `export` 机制 `导出对象`。 |
| 27 | + |
| 28 | +在 `export` 机制调用前,我们需要保证导出的对象已经被定义,比如: |
| 29 | + |
| 30 | +```python |
| 31 | +varA = "varA" |
| 32 | + |
| 33 | + |
| 34 | +def funcA(): |
| 35 | + return "funcA" |
| 36 | +``` |
| 37 | + |
| 38 | +在确保定义之后,我们可以从 `nonebot.plugin` 导入 `export()` 方法, `export()` 方法会返回一个特殊的字典 `export`: |
| 39 | + |
| 40 | +```python |
| 41 | +from nonebot.plugin import export |
| 42 | + |
| 43 | +export=export() |
| 44 | +``` |
| 45 | + |
| 46 | +这个字典可以用来装载导出的对象,它的 key 是对象导出后的命名,value 是对象本身,我们可以直接创建新的 `key` - `value` 对导出对象: |
| 47 | + |
| 48 | +```python |
| 49 | +export.vA = varA |
| 50 | +export.fA = funcA |
| 51 | +``` |
| 52 | + |
| 53 | +除此之外,也支持 `嵌套` 导出对象: |
| 54 | + |
| 55 | +```python |
| 56 | +export.sub.vA = varA |
| 57 | +export.sub.fA = funcA |
| 58 | +``` |
| 59 | + |
| 60 | +特别地,对于 `函数对象` 而言,`export` 支持用 `装饰器` 的方法来导出,因此,我们可以这样定义 `funcA`: |
| 61 | + |
| 62 | +```python |
| 63 | +@export.sub |
| 64 | +def funcA(): |
| 65 | + return "funcA" |
| 66 | +``` |
| 67 | + |
| 68 | +或者: |
| 69 | + |
| 70 | +```python |
| 71 | +@export |
| 72 | +def funcA(): |
| 73 | + return "funcA" |
| 74 | +``` |
| 75 | + |
| 76 | +通过 `装饰器` 的方法导出函数时,命名固定为函数的命名,也就是说,上面的两个例子等同于: |
| 77 | + |
| 78 | +```python |
| 79 | +export.sub.funcA = funcA |
| 80 | + |
| 81 | +export.funcA = funcA |
| 82 | +``` |
| 83 | + |
| 84 | +这样,我们就成功导出 `varA` 和 `funcA` 对象了。 |
| 85 | + |
| 86 | +下面我们将介绍如何在 `pluginB` 中导入这些对象。 |
| 87 | + |
| 88 | +### 使用 require |
| 89 | + |
| 90 | +在 `pluginB` 中,我们调用 `require` 机制 `导入对象`。 |
| 91 | + |
| 92 | +:::warning 警告 |
| 93 | + |
| 94 | +在导入来自其他插件的对象时, 请确保导出该对象的插件在引用该对象的插件之前加载。如果该插件并未被加载,则会尝试加载,加载失败则会返回 `None`。 |
| 95 | + |
| 96 | +::: |
| 97 | + |
| 98 | +我们可以从 `nonebot.plugin` 中导入 `require()` 方法: |
| 99 | + |
| 100 | +```python |
| 101 | +from nonebot.plugin import require |
| 102 | +``` |
| 103 | + |
| 104 | +`require()` 方法的参数是插件名, 它会返回在指定插件中,用 `export()` 方法创建的字典。 |
| 105 | + |
| 106 | +```python |
| 107 | +require_A = require('pluginA') |
| 108 | +``` |
| 109 | + |
| 110 | +在之前,这个字典已经存入了 `'vA'` - `varA`, `'fA'` - `funcA` 或 `'funcA'` - `funcA` 这样的 `key` - `value` 对。因此在这里我们直接用 `属性` 的方法来获取导入对象: |
| 111 | + |
| 112 | +```python |
| 113 | +varA = require_A.vA |
| 114 | +funcA = require_A.fA or require_A.funcA |
| 115 | +``` |
| 116 | + |
| 117 | +这样,我们就在 `pluginB` 中成功导入了 `varA` 和 `funcA` 对象了。 |
0 commit comments