当前位置: 首页 > 后端技术 > Python

PythonSnack最佳实践

时间:2023-03-25 20:48:05 Python

了解linux的人应该都听说过Newt。Newt是为RedHat安装程序设计的基于文本的窗口开发工具。它是用c语言编写的,不依赖于X包。linux下可用dialog和whiptail都是基于它的。我们今天要讨论的小吃是Newt提供的python接口。redhat系统自带这个模块。本文讲解如何使用snack制作伪终端页面,并配合代码展示实现效果。为什么说前言是最佳实践呢?因为在使用snack的过程中,我在网上查了相关资料,发现的相关资料很少。偶尔有几篇都是API或者Demo级别的文章,内容并不全面,更不用说高级的扩展功能了。正好在工作中,需要为我们的一个系统做一个终端部署控制台UI,所以就使用了pythonsnack来实现。期间不断更新迭代新的需求,从基础页面到增删改查,再到验证,再到Configuration导入,再到进度条等等,不断的迭代开发让我为了加深对snack的理解,不管支持不支持,我都尝试过一一解决,所以这里把我这段时间的收货做一个总结,分享给需要的人。具体场景本文实践需求是制作一个部署控制台工具,主要分为三个阶段:基础配置、高级配置、部署进度。基础配置页面需要我们创建一些主机,填写一些主机信息,比如IP、Hostname和Password,然后我们还需要创建一些主机进行高级配置,但是我们可以复用有基本设置的主机,所以我们的tools必须支持高级配置中导入基础配置的功能,我们在高级配置中还有一个全局配置,不局限于单个主机的配置(具体的部署原则和是非,我就不去了详细介绍,这不是本文的重点)。最后是进度条页面,我们可以在这里展示部署过程的阶段和相关的时间信息。项目地址:https://github.com/tony-yin/B...冷盘古时候,先上几道凉菜来开胃。所谓凉菜,就是介绍蟒蛇小吃的基本成分。基础组件有很多,类似html,主要有:TextboxTextboxReflowedButtonCompactbuttonCheckboxListboxSingleRadioButtonScaleEntry然后是一些组合组件,是基于上面基础组件封装得到的,主要有:RadioBarButtonBarCheckboxTree以上组件都是基础组件(组合组件也算是基础组件),这些组件需要网格和表单来渲染。Grid是“网格”的意思。它类似于html中的表格,由行和列组成。我们的基础组件需要放在网格中,实现页面布局;而表单类似于一个“表单”,我们需要将网格填充到表单中,运行之后就可以看到图形页面了。介绍完工业革命的基本成分,想必大家对零食的成分有了充分的了解。这时候可以参考文末的参考资料做几个小demo。做了之后,你会发现页面出来了,emmm。。。但是感觉好繁琐,重复的代码很多,页面布局也很怪异。如果你想让布局更好,你需要添加很多代码。我们把使用基本组件的阶段称为“上古时代”。每次我们制作一扇窗户时,我们都必须慢慢地一砖一瓦地建造它。这样效率太低了,所以我们迫切需要一波“工业革命”来提高生产力。Pythonsnack似乎考虑到了这个问题。除了上述基本组件外,它还提供了对话框相关的组件。对话组件是大师级的。一个对话框组件就是一个窗口,也就是我们上面说的窗体,窗体中填充了各种必要的基础组件,对话框组件主要包括:肉,却怀念乡间的游戏。同样,我们看惯了“工业革命”的产品,发现虽然可用,但也仅仅停留在基本可用的水平。如果我们想改变样式,增加自己的定制需求,那是有限的,根本无法满足新的需求。要求的技术实现要求。因此,我们不能只用别人实现的现成产品,我们可以尝试“返璞归真”,回到最初的“远古时代”,自己实现一场“工业革命”。所谓“对话”组件无非是对基本组件的封装。我们也可以实现自己的组件库,在前端很流行,比如font-awesome,iview,ant-design等。这里我们实现了如下对话框:按钮样式扩展布局大小自动扩展深色文字输入框扩展弹出窗口扩展进度条窗口信息显示扩展动态显示扩展扩展组件库地址:widgetextend主菜冷菜库不够用,让主菜一起来。以上是pythonsnack的API列表。做个小demo还可以,但离产品化还有很远的距离。接下来,根据我部署控制台工具的实践经验,分享几个“菜”。必须够硬,不接受反驳,不接受批评,O(∩_∩)O~Hotkeypythonsnack提供了两种方式帮助用户使用,一种是窗口底部的操作提示栏,和另一个是热键。热键是快捷键。比如我们可以按键盘上的ESC键返回页面。我们可以通过调用grid的runOnce接口获取hotkey输入,例如hotkey=g.runOnce(),然后根据hotkey的值进行判断并进行相应的操作。页面切换当我们有多个页面时,我们需要页面切换的功能。浏览文档后,我们并没有发现类似的功能。在我们的工具中,切换页面的方式主要有两种,一种是点击按钮,另一种是热键。由于没有原生的页面切换接口,我们根据触发方式手动切换页面。比如我们想点击第1页的下一个按钮,想跳转到第2页,那么我们只需要获取按钮的返回值,判断是否是下一个即可。如果是next,我们直接调用页面2的方法即可。热键也是一样的,就是判断热键内容是否是对应的热键。ret,button,lb=ExtListboxChoiceWindow(screen,'分布存储配置','分布存储配置',ips,buttons=("prev","next","exit"),width=50,height=5,)if按钮==“退出”或ret==“ESC”:屏幕。finish()elifbutton=="prev":Welcome_Deploy_Window()elifbutton=="next":Additional_Config_Window()eliflbisnotNone:Basic_Host_Window(lb)增删改查增删改查是始终是软件系统无法避免的基本功能。“查看”:首先是一个整体视图,我们可以通过一个列表来展示所有的信息,这时候我们可以使用ExtListboxChoiceWindow组件来实现;然后是单条查看,我们可能有多条信息,当我们想查看单条信息的详细信息时,可以点击具体的某一项进入详细信息对话框,如何实现呢?listbox中有一个current的概念,就是每一个li在listbox中的唯一标识。我们可以用列表的索引来填充它,因为很多时候列表页面的信息无非就是一个数组或者一个列表。我们获取当前的current,也就是获取数组的index,然后根据index去查value。然后我们调用新页面并将找到的值分配给文本框。文本框有一个setText来执行此操作。当然,我们的ExtEntryWindow组件也可以填充赋值。请参考上面代码中的lb,其实就是listbox的li.current()接口。“添加”:我们可以使用new按钮或者listbox中的一个li作为新按钮来触发新的操作。单击后,将出现一个对话框。对话框中有一些Textbox、Radio、Checkbox等。defBasic_Host_Window(current,data=None):buttons=['save','cancel','exit']如果不是data:data=['IPAddress:','Hostname:','Password:']ifcurrent!='add':data=get_format_data(Basic_Config[current],BASIC_TYPE)buttons.insert(1,'Delete')host=ExtEntryWindow(screen,'{}host'.format('Add'ifcurrent=='add'else'Edit'),'Pleasefillstoragehostinfo.',data,width=40,entryWidth=40,buttons=buttons)"Change":修改的方法是在列表页选择要修改的项目,然后进入详情页,可以查看创建时填写的信息,也就是我们在“查看”中提到的单条信息的方式。我们需要做的是在用户点击保存按钮时获取编辑好的数据,然后进行一次修改即可。在我们的工具中,这个操作就是根据索引修改数组中索引对应的数据。“删除”:只要有添加就删除。我还没有实现批量删除功能。一方面pythonsnack支持的功能有限,另一方面时间有限,所以只实现了单条删除功能。只需在编辑页面添加一个删除按钮即可。为了提醒用户误删除,我们还需要添加一个确认提示框。ifhost[1]=="delete":button=ExtButtonChoiceWindow(screen,'Deletehost','Areyousuretodeletecurrenthost?')ifbutton=="ok":del(Basic_Config[current])else:Basic_Host_Window(current)组件扩展对于构建您自己的组件库是非常必要的。对于默认的按钮样式,我真的不想吐槽了。它仍然认为它的边界很好?!所以我们自己搭建组件库的初衷是把每个dialog里面的button改成compactbutton。没办法,默认的dialog组件是不会变的,只好原地踏步。当然,我们不会因为一个按钮样式就去扩展组件库,有很多新的需求是依赖于我们扩展的组件。比如热键,原生对话框不支持热键;还有进度条的进度时间和任务信息的显示;还有Gridform的动态布局等等,具体细节就不一一介绍了。如果想了解更多,直接看代码,做个小demo,一目了然。爽口的甜菜馅主菜已经吃饱了,是时候来一波甜菜漱口解渴了。制作进度条页面时,除了显示进度任务的完成信息外,还想显示开始时间和花费的时间。发现python的time模块比较坑爹,不支持时差转换。我只发现datetime可以将时差转换为微秒、秒、小时三个单位,但是我想实现时差的自动转换,即60s自动转换为1min,60min自动转换为1h,24h转换为1d,天外我不转换,逻辑不难,拿出来分享给有需要的人就好了,不用另起炉灶。defget_time_interval(start_time):start_time=datetime.fromtimestamp(start_time)now_time=datetime.fromtimestamp(time.time())interval=(now_time-start_time).secondsformat_interval=get_format_interval(interval)returnformat_intervaldefget_format_interval(interval):如果间隔<60:format_interval="{}s".format(str(interval))elif60<=interval<60*60:format_interval="{}min{}s".format(str(interval/60),str(interval%60))elif60*60<=interval<60*60*24:format_interval="{}h{}min{}s".format(str(interval/(60*60)),str(interval%(60*60)/60),str(interval%(60*60)%60))elif60*60*24<=interval:format_interval="{}d{}h{}min{}s".format(str(间隔/(60*60*24)),str(间隔%(60*60*24)/60*60),str(interval%(60*60)/60),str(interval%(60*60)%60))returnformat_intervalMealSummary本来只是想做一个终端图形化的进度条页面,但是后续需求越来越多,导致出现了一个部署控制台工具,整个项目的开发和优化用了两周左右,项目中遇到的很多困难和问题与pythonsnack无关,所以不做详细说明,比如上面提到的甜菜,有兴趣的可以自行阅读代码。pythonsnack中还有很多我没有用过的未知数,比如checkboxtree等等,但是我相信一切都是一样的。通过这种做法,其他组件应该不会花费很多时间来使用和扩展。其实我感受最深的就是前端的飞速发展。Pythonsnack是2000年代初期的产物。和jQuery相比,很多页面逻辑都弱了很多,更不用说现在了。Angular、Vue等,只是领域不一样。毕竟是伪终端页面。能弄成这样也不错。如果是真正的桌面图形界面(GUI),有pyqt这样的神器,貌似很强大。在之前的一个项目中,我使用了pythonsnack做的console。当然,我不知道它是用这种技术制成的。的。这次很巧合,需要做这样一个工作用的控制台。在工作中学习和使用自己感兴趣的技术,感觉真的很酷。在工作中使用技术与在业余时间学习新技术并制作一个小演示完全不同。工作中对技术的运用会有新的需求,我们将不断精益求精,深耕细作。所以,以工作为平台,实现自己的技术价值,会有很大的成就感,分享给大家。(#^.^#)