摘要这里我们介绍Python的库MonkeyType, 他可以自动帮助我们生成变量的类型和返回值的类型. 这里简单介绍MonkeyType的使用和可能会遇到的编码的错误.
简介
在写Python代码的时候, 有的时候为了代码更加完善, 我们会在定义函数的时候给出参数的类型, 同时也会格式return的类型, 如下所示:
def add(a: int, b: int) -> int:
return a + b
这个时候, 我们可以使用MonkeyType这个库来自动完成. 下面简单介绍一下用法. MonkeyType的Github链接, Github, Instagram-MonkeyType
MonkeyType用法介绍
MonkeyType的安装
pip install monkeytype
MonkeyType的使用
下面使用一个简单的例子来说明使用方法. 测试文件的结构如下所示:
D:.
│─ test.py
│
└─some
─ addFunction.py
─ __init__.py
假设我们写的module叫some, some下有一个文件为addFunction.py, 里面定义了一个实现加法的类. 我们没有定义变量的类型 (一会我们使用MonkeyType自动加上). 定义的类如下所示:
class add_number(object):
"""这是一个加法运算
"""
def __init__(self, a, b):
self.a = a
self.b = b
def add_n(self):
c = self.a + self.b
return c
为了对add_number添加相关的变量类型, 我们写一个脚本为test.py, 其中会调用add_number. test.py的内容如下所示, 我们初始化add_number类, 并调用其中的方法:
from some.addFunction import add_number
add_number(1,2).add_n()
接着运行test.py文件, 注意这里使用monkeytype run运行. 完成的命令如下所示:
monkeytype run test.py
运行之后会生成一个monkeytype.sqlite3的文件. 之后我们在运行monkeytype stub some.module可以打印出更改之后的样子. 例如在我们这个例子里我们应该运行下面的命令.
monkeytype stub some.addFunction
当然我们也可以直接对原始的文件进行修改, 直接运行monkeytype apply some.module即可. 例如在我们这个例子中, 我们应该运行下面的命令.
monkeytype apply some.addFunction
他会自动对addFunction.py文件进行直接的修改. 修改之后的内容为:
class add_number(object):
"""这是一个加法运算
"""
def __init__(self, a: int, b: int) -> None:
self.a = a
self.b = b
def add_n(self) -> int:
c = self.a + self.b
return c
这样我们就增加了相应的变量的类型和返回值的类型.
出现UnicodeDecodeError的报错
如果在使用monkeytype apply some.module的时候出现如下的报错,
UnicodeDecodeError: 'gbk' codec can't decode byte 0x9c in position 109: illegal multibyte sequence
这可能是因为我们在要修改的文件是使用utf-8进行编码的. 我们需要修改一下monkeytype的源文件. 打开如下路径的文件:
\python38\lib\site-packages\monkeytype\cli.py
找到函数apply_stub_handler, 找到read_text和write_text, 在里面加上参数encoding="UTF-8". 完整的函数如下所示, 我们修改了第11和第14行.
def apply_stub_handler(args: argparse.Namespace, stdout: IO, stderr: IO) -> None:
stub = get_stub(args, stdout, stderr)
if stub is None:
complain_about_no_traces(args, stderr)
return
module = args.module_path[0]
mod = importlib.import_module(module)
source_path = Path(inspect.getfile(mod))
source_with_types = apply_stub_using_libcst(
stub=stub.render(),
source=source_path.read_text(encoding="UTF-8"),
overwrite_existing_annotations=args.existing_annotation_strategy == ExistingAnnotationStrategy.IGNORE,
)
source_path.write_text(source_with_types, encoding="UTF-8")
print(source_with_types, file=stdout)