如何设计接受 Python 函数或代码的命令行界面 (CLI)?
How to design a command line interface (CLI) which accepts Python functions or code?
我有一个函数可以根据特定规则解析给定的字符串。我想为这个功能设计一个 CLI 界面。但问题是我希望用户能够使用自己的 READER & WRITER 函数通过 CLI 调用此函数。为了清楚起见,这里有一个示例代码和我要解释的内容的演示。
# mylib.py
# piece of code that belongs to my lib
def parser(_id, text):
# parse the text & do some magic
return (_id, parsed_text)
# user-side code
def reader():
# read from a database
# or file or network or who knows where
yield (_id, text)
# user-side code
def writer(_id, text):
# write to somewhere
return True # or false depends on write action
示例调用应该是这样的:
$ python mylib.py --reader <something-that-I-dont-know>
我不想使用 eval
技巧,但我也希望用户在将数据传递到我的库时应该灵活。这可能吗?或者我应该尝试另一种方法?
在@AlexHall 的帮助下,我想出了以下解决方案:
import pathlib
import importlib.util
def load_module(filepath):
module_path = pathlib.Path(filepath)
abs_path = module_path.resolve()
module_name = module_path.stem
spec = importlib.util.spec_from_file_location(module_name, abs_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
使用此功能,即使模块不在路径中,我也能够导入文件系统中存在的任何有效 python 模块。
这是一个示例用法:
parser = make_parser(prog="tokenizer")
args = parser.parse_args()
module = load_module(args.writer) # if nothing is passed, default action defined in the parser
writer = module.writer
module = load_module(args.reader)
reader = module.reader
# do what you want to do with them
我有一个函数可以根据特定规则解析给定的字符串。我想为这个功能设计一个 CLI 界面。但问题是我希望用户能够使用自己的 READER & WRITER 函数通过 CLI 调用此函数。为了清楚起见,这里有一个示例代码和我要解释的内容的演示。
# mylib.py
# piece of code that belongs to my lib
def parser(_id, text):
# parse the text & do some magic
return (_id, parsed_text)
# user-side code
def reader():
# read from a database
# or file or network or who knows where
yield (_id, text)
# user-side code
def writer(_id, text):
# write to somewhere
return True # or false depends on write action
示例调用应该是这样的:
$ python mylib.py --reader <something-that-I-dont-know>
我不想使用 eval
技巧,但我也希望用户在将数据传递到我的库时应该灵活。这可能吗?或者我应该尝试另一种方法?
在@AlexHall 的帮助下,我想出了以下解决方案:
import pathlib
import importlib.util
def load_module(filepath):
module_path = pathlib.Path(filepath)
abs_path = module_path.resolve()
module_name = module_path.stem
spec = importlib.util.spec_from_file_location(module_name, abs_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
使用此功能,即使模块不在路径中,我也能够导入文件系统中存在的任何有效 python 模块。
这是一个示例用法:
parser = make_parser(prog="tokenizer")
args = parser.parse_args()
module = load_module(args.writer) # if nothing is passed, default action defined in the parser
writer = module.writer
module = load_module(args.reader)
reader = module.reader
# do what you want to do with them