CMDR Python库的异步实现。
asynccmd的Python项目详细描述
异步命令
CMD Python库的异步实现。
AsyncCMD是一个库,用于为AsyncIO构建命令行接口 项目。
它非常简单,就像原始的命令库 https://docs.python.org/3.6/library/cmd.html。
机修工很相似。你有命令超类,你可以重写 类方法并添加您自己的方法。
功能
- 支持Windows和POSIX系统的命令行
- 内置help或?命令以列出所有可用的命令
- 内置exit命令,用于紧急停止异步循环
- 通过发送空字符串支持repeat last cmd命令
开始
简单示例
这是一个非常简单的示例,向您展示主要功能以及它们如何 被利用。
首先,我们要创建一个新类并继承我们的Cmd类。 不要实例化Cmd本身。
创建这个新类的实例并运行循环。
classSimpleCommander(Cmd):def__init__(self,mode,intro,prompt):# We need to pass in Cmd class mode of async cmd runningsuper().__init__(mode=mode)self.intro=introself.prompt=promptself.loop=Nonedefdo_tasks(self,arg):""" Our example method. Type "tasks <arg>" :param arg: contain args that go after command :return: None """fortaskinasyncio.Task.all_tasks(loop=self.loop):print(task)defstart(self,loop=None):# We pass our loop to Cmd class.# If None it try to get default asyncio loop.self.loop=loop# Create async tasks to run in loop. There is run_loop=false by defaultsuper().cmdloop(loop)# For win system we have only Run mode# For POSIX system Reader mode is preferredifsys.platform=='win32':loop=asyncio.ProactorEventLoop()mode="Run"else:loop=asyncio.get_event_loop()mode="Reader"# create instancecmd=SimpleCommander(mode=mode,intro="This is example",prompt="example> ")cmd.start(loop)# prepaire instancetry:loop.run_forever()# our cmd will run automatilly from this momentexceptKeyboardInterrupt:loop.stop()
一般示例
我们使用简单的示例,但是添加了一些新人员:*sleep_n_print 将从cli命令*do_sleepnew调用的协程 向事件循环添加任务的方法(sleep cli命令)
asyncdefsleep_n_print(loop,time_to_sleep=None):""" This is our simple coroutine. :param time_to_sleep: time to sleep in seconds :return: await sleep for time_to_sleep seconds """asyncio.set_event_loop(loop)# set correct event loopawaitasyncio.sleep(int(time_to_sleep))print("Wake up! I was slept for {0}s".format(time_to_sleep))
defdo_sleep(self,arg):""" Our example cmd-command-method for sleep. sleep <arg> :param arg: contain args that go after command :return: None """self.loop.create_task(sleep_n_print(self.loop,arg))
运行cli并发出sleep 10命令3次。现在我们有3个 sleep_n_print事件循环中的异步任务。如果使用tasks 指挥部,你看到类似的东西了。
example>tasks <Task pending coro=<sleep_n_print() running at asynccmd\examples\main.py:13> wait_for=<Future pending cb=[Task._wakeup()]>> <Task pending coro=<Cmd._read_line() running at C:\Program Files\Python35\lib\site-packages\asynccmd\asynccmd.py:141>> <Task pending coro=<sleep_n_print() running at asynccmd\examples\main.py:13> wait_for=<Future pending cb=[Task._wakeup()]>> <Task pending coro=<sleep_n_print() running at asynccmd\examples\main.py:13> wait_for=<Future pending cb=[Task._wakeup()]>> example> Wake up! I was slept for 10s Wake up! I was slept for 10s Wake up! I was slept for 10s
aiohttp实现
这是一个如何控制aiohttp实例的实际例子。我们将 创建两个cli命令start和stop。此命令获取端口 数字只能作为一个参数。让我们为将军做些改变 示例:
创建类助手,为我们做所有的aiohttp工作人员。
classAiohttpCmdHelper:""" Helper class that do all aiohttp start stop manipulation """port=8080# Default portloop=None# By default loop is not setdef__init__(self,loop,port):self.loop=loopself.port=portasyncdefhandle(self,request):""" Simple handler that answer http request get with port and name """name=request.match_info.get('name',"Anonymous")text='Aiohttp server running on {0} port. Hello, {1}'.format(str(self.port),str(name))returnweb.Response(text=text)asyncdefstart(self):""" Start aiohttp web server """self.app=web.Application()self.app.router.add_get('/',self.handle)self.app.router.add_get('/{name}',self.handle)self.handler=self.app.make_handler()self.f=self.loop.create_server(self.handler,host='0.0.0.0',port=self.port)# Event loop is already runing, so we await create server instead# of run_until_completeself.srv=awaitself.fasyncdefstop(self):""" Stop aiohttp server """self.srv.close()awaitself.srv.wait_closed()awaitself.app.shutdown()awaitself.handler.shutdown(60.0)awaitself.app.cleanup()
现在我们准备将start和stop命令添加到Commander。
# Add property to store helper objectsaiohttp_servers=[]# ...defdo_start(self,arg):""" Our example cli-command-method for start aiohttp server. start <arg> :param arg: Port number :return: None """ifnotarg:# we use simple check in our demonstrationprint("Error port is empty")else:test=AiohttpCmdHelper(loop=self.loop,port=int(arg))self.aiohttp_servers.append({'port':int(arg),'server':test})self.loop.create_task(test.start())defdo_stop(self,arg):""" Our example cli-command-method for stop aiohttp server. start <arg> :param arg: Port number :return: None """ifnotarg:# we use simple check in our demonstrationprint("Error! Provided port is empty")else:aiohttp_servers=[]forsrvinself.aiohttp_servers:ifsrv['port']==int(arg):self.loop.create_task(srv['server'].stop())else:aiohttp_servers.append({'port':srv['port'],'server':srv['server']})self.aiohttp_servers=aiohttp_servers
我们需要在main中添加asyncio.set_event_loop(loop)addition 阻止aiohttp创建自己的循环的示例。
ifsys.platform=='win32':loop=asyncio.ProactorEventLoop()mode="Run"else:loop=asyncio.get_event_loop()mode="Reader"asyncio.set_event_loop(loop)# set our event loop for aiohttp (fix for Win32)
就这些。现在我们可以从代码中运行多个aiohttp服务器。
文件
待定
贡献
主流是fork项目、提交更改和发送pull请求。 对lib的贡献可以通过反馈、bug报告或 拉取请求。投稿.md-待定。
要求
- python>;=3.5
许可证
asynccmd是在apache 2许可下提供的。
源代码
最新的开发人员版本可在 https://github.com/valentinmk/asynccmd