python, menu module

快乐田伯光 2010-12-27 03:37:51
大家好,我想问一下python有没有内置适用于创建纯文本菜单的模块,菜单形式如下:

a) do something
b) do something
c) do something

your choice:
...全文
258 25 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
mirguest 2011-01-24
  • 打赏
  • 举报
回复
我用类写了一个。http://hi.baidu.com/mirguest/blog/item/381fd232c8f59f8aa8018e6a.html
代码如下:

# -*- coding:utf-8 -*-

class Menu(object):
def __init__(self,label):
self.label=label

def click(self):
pass

class callbackMenu(Menu):
def __init__(self,label,callback,father=None):
self.label=label
self.rcallback=callback
self.rfather=father

def click(self,*args,**kwds):
print "currentClick",self.label
print
if callable(self.rcallback):
self.rcallback(*args,**kwds)
else:
return None

class subMenu(Menu):
def __init__(self,label,submenu,father=None):
self.label=label
self.rsubmenu=submenu
self.rfather=father

def show(self):
for i,sub in enumerate(self.rsubmenu):
print "[%d] %s"%(i,sub.label)


def click(self):
print "currentMenu",self.label
self.show()

def showfather(p):
if(hasattr(p,"rfather") and p.rfather==None):
print p.label
return
print p.label,'<-',
showfather(p.rfather)

def showfather2(p,symbol='->'):
if p.rfather==None:
print p.label,
return
showfather2(p.rfather,symbol)
print symbol,p.label,


def handle(p):
while True:
print '-'*40
showfather2(p)
print
p.click()
try:
get=raw_input("Input:")
if get in ['q','Q']:
break
get=int(get)
if get==100:
if hasattr(p,"rfather") and p.rfather!=None:
p=p.rfather
continue
if isinstance(p.rsubmenu[get],callbackMenu):
p.rsubmenu[get].click()
elif isinstance(p.rsubmenu[get],subMenu):
fp=p
p=p.rsubmenu[get]
p.rfather=fp
except:
print "Wrong Input"

if __name__=='__main__':
sub=subMenu("sub",[callbackMenu("cb1",None),
callbackMenu("cb2",None)])
sub2=subMenu("sub2",[callbackMenu("cb2_1",None),
callbackMenu("cb2_2",None)])
sub3=subMenu(
"sub3",
[subMenu("subsub1",
[callbackMenu("subcb1",None),
callbackMenu("subcb2",None)]),
subMenu("subsub2",
[callbackMenu("sub2cb1",None),
callbackMenu("sub2cb2",None)])])
main=subMenu("Main",[sub,sub2,sub3])
handle(main)

在这里,我用输入100来返回上一级菜单。
快乐田伯光 2011-01-11
  • 打赏
  • 举报
回复
你说得功能正是我的目的啊,我实现得比你说得感觉简单哦. 下面是个例子:
main_menu.py

#!/usr/bin/env python

import menu_util

def func_b(menu_path_list):
'''
'''
print 'print in func_b()'
return 0

root_menu_dict = {
1 : ('1st_a', 'sub_a.py'),
2 : ('1st_b', func_b),
}

if __name__ == '__main__':
menu_util.menu_manage(['root'], root_menu_dict)


sub_a.py

#!/usr/bin/env python

import menu_util

def sub_sub_sub_a(menu_path_list):
print 'in sub_sub_sub_a()'
return 0

def sub_sub_sub_b(menu_path_list):
print 'in sub_sub_sub_b()'
return 0

def sub_sub_menu_a(menu_path_list):
'''
'''
sub_sub_menu_a_dict = {
1 : ('3rd_a', sub_sub_sub_a),
2 : ('3rd_b', sub_sub_sub_b),
}
return menu_util.menu_manage(menu_path_list, sub_sub_menu_a_dict)

sub_a_menu_dict = {
1 : ('2nd_a', sub_sub_menu_a),
2 : ('2nd_b', 'sub_sub_b.py'),
}

def main(menu_path_list):
'''
'''
return menu_util.menu_manage(menu_path_list, sub_a_menu_dict)


sub_sub_b.py

#!/usr/bin/env python

def main(menu_path_list):
'''
'''
print 'in sub_sub_b.main()'

return 6


下面是运行结果:

[root@louis menu]# ./main_menu.py
root:
1) 1st_a
2) 1st_b

Select option number ( b>ack or l>ist ) (b): 1
root -> 1st_a:
1) 2nd_a
2) 2nd_b

Select option number ( b>ack or l>ist ) (b): 1
root -> 1st_a -> 2nd_a:
1) 3rd_a
2) 3rd_b

Select option number ( b>ack or l>ist ) (b): 1
in sub_sub_sub_a()

Select option number ( b>ack or l>ist ) (b): l

root -> 1st_a -> 2nd_a:
1) 3rd_a
2) 3rd_b

Select option number ( b>ack or l>ist ) (b): 2
in sub_sub_sub_b()

Select option number ( b>ack or l>ist ) (b): l

root -> 1st_a -> 2nd_a:
1) 3rd_a
2) 3rd_b

Select option number ( b>ack or l>ist ) (b): b
root -> 1st_a:
1) 2nd_a
2) 2nd_b

Select option number ( b>ack or l>ist ) (b): 2
in sub_sub_b.main()
root -> 1st_a:
1) 2nd_a
2) 2nd_b

Select option number ( b>ack or l>ist ) (b): b
root:
1) 1st_a
2) 1st_b

Select option number ( b>ack or l>ist ) (b): 2
print in func_b()

Select option number ( b>ack or l>ist ) (b):



[Quote=引用 17 楼 fibbery 的回复:]
我不会写Python代码,但我觉得你的菜单可以这样设计,个人觉得扩展性和灵活性都比较好。
如果,需要撤销与重做操作,你还需要简历一个CCommand链,下面没有展示CCommand链。

C/C++ code
class CCommand//抽象类,根据需要派生不同的Command,在不同的菜单中调用
{
public:
do();
redo();
};

class……
[/Quote]
notax 2011-01-10
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 guosha 的回复:]

呵呵, 前几天刚好发贴问了这个问题, 只是奇怪当时你咋不积极回答?
引用 18 楼 notax 的回复:
哦,忘了说,

Python code

def sf():
'''
just a test function
'''
pass



也是多余的

type(xxx) ==
可以这样用isinstance

>>> def f():pass
...……
[/Quote]

前些日子太忙了,啥也顾不上了,
看了之前的回复,也没啥不同,callable 也行吧,
对比type,现在大多见义用isinstance,
其他的可以看一看python style guide吧

python的风格还是比较同一的
notax 2011-01-09
  • 打赏
  • 举报
回复


呵呵,这个吗..

input_str in ['', 'b']:

比较特别
快乐田伯光 2011-01-09
  • 打赏
  • 举报
回复
输入b或是直接回车返回上一级菜单,

[Quote=引用 19 楼 notax 的回复:]
呵呵,这个吗..

input_str in ['', 'b']:

比较特别
[/Quote]
快乐田伯光 2011-01-09
  • 打赏
  • 举报
回复
呵呵, 前几天刚好发贴问了这个问题, 只是奇怪当时你咋不积极回答?
[Quote=引用 18 楼 notax 的回复:]
哦,忘了说,

Python code

def sf():
'''
just a test function
'''
pass



也是多余的

type(xxx) ==
可以这样用isinstance

>>> def f():pass
...
>>> import types
>>> isi……
[/Quote]
快乐田伯光 2011-01-09
  • 打赏
  • 举报
回复
else:
#do nothing
pass

我觉得表示清晰的作用远大于少写一条语句。 个人喜好!

[Quote=引用 16 楼 notax 的回复:]
引用 14 楼 guosha 的回复:

1.
exec 好像可以用__import__代替

不可以, 我要取返回值, 做菜单显示控制

2.
if ret == 6: .. else 是多鱼的
如上, 返回6表示从下一级菜单返回.

3.
for_menu_key in sorted(menu_dict):
=
for menu_key in sorted(menu……
[/Quote]
fibbery 2011-01-08
  • 打赏
  • 举报
回复
我不会写Python代码,但我觉得你的菜单可以这样设计,个人觉得扩展性和灵活性都比较好。
如果,需要撤销与重做操作,你还需要简历一个CCommand链,下面没有展示CCommand链。
class CCommand//抽象类,根据需要派生不同的Command,在不同的菜单中调用
{
public:
do();
redo();
};

class CMenuItem
{
list<CMenuItem *> m_children;
CMenuItem * m_parent;
Command * m_cmd; //所要执行的任务对象
public:
printChildrenMenu();//当选择该菜单时,显示下级子菜单,即打印所以子菜单
AddCommand(Command & cmd);//一般来说,只有叶子节点菜单才会有,
//但也不排除非叶子节点也执行功能,增强菜单灵活性
};

class CTextMenu
{
CMenuItem & m_cursor=m_root;
CMenuItem m_root;
public:
CmenuItem & addMenuItem(CMenuItem & parent,CMenuItem & added);//return added
};

notax 2011-01-08
  • 打赏
  • 举报
回复
哦,忘了说,

def sf():
'''
just a test function
'''
pass


也是多余的

type(xxx) ==
可以这样用isinstance

>>> def f():pass
...
>>> import types
>>> isinstance(f, types.FunctionType)
True
>>>
上帝无言 2011-01-07
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 guosha 的回复:]
不是不可以,是优雅不优雅的问题,
就像几十条if语句可以用一个字典结构来替


引用 3 楼 a590687 的回复:
用''' 菜单''' 三引号 不是就可以么
[/Quote]
今天又看到这个,要优雅的是不是做GUI发看点啊。pyqt4?
notax 2011-01-07
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 guosha 的回复:]

1.
exec 好像可以用__import__代替

不可以, 我要取返回值, 做菜单显示控制

2.
if ret == 6: .. else 是多鱼的
如上, 返回6表示从下一级菜单返回.

3.
for_menu_key in sorted(menu_dict):
=
for menu_key in sorted(menu_dict.keys()……
[/Quote]


1.可以吧

$ cat hello.py
def main(s):
return 1


>>> hello = __import__('hello')
>>> print hello.main('abc')
1


2.说的是 else, #do nothing

3. 可以吧


俺写的文本菜单肯定没curses 好,也就算了吧
快乐田伯光 2011-01-07
  • 打赏
  • 举报
回复
你若有更好的实现,不防写于大家共享一下
[Quote=引用 13 楼 notax 的回复:]
俺不大懂哦,也没祥细看 其他的,感觉怪怪的哦
[/Quote]
快乐田伯光 2011-01-07
  • 打赏
  • 举报
回复
1.
exec 好像可以用__import__代替

不可以, 我要取返回值, 做菜单显示控制

2.
if ret == 6: .. else 是多鱼的
如上, 返回6表示从下一级菜单返回.

3.
for_menu_key in sorted(menu_dict):
=
for menu_key in sorted(menu_dict.keys()):

初用python不久, dict可以直接按key排序?




notax 2011-01-07
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 guosha 的回复:]

我已经自己写了一个,用它写了一个不小的系统管理菜单,感觉还不错。代码如下:
Python code

#!/usr/bin/env python
'''
Description: This is a menu manage module, it take a dictory data struct as a input and output a text menu
Author: ……
[/Quote]

1.
exec 好像可以用__import__代替

2.
if ret == 6: .. else 是多鱼的

3.
for_menu_key in sorted(menu_dict):
=
for menu_key in sorted(menu_dict.keys()):



俺不大懂哦,也没祥细看 其他的,感觉怪怪的哦
fibbery 2011-01-07
  • 打赏
  • 举报
回复
让我想起来上大学的时候的课程设计了,模拟CPU调度。当时就是写了一个看上去很漂亮的纯文本菜单,可是现在想起来那些实现的代码,真是难看。

所以,程序的界面美不美关与程序代码是否优雅是两回事儿。
快乐田伯光 2011-01-07
  • 打赏
  • 举报
回复
优雅不优雅跟GUI有什么必然关系呢?

[Quote=引用 6 楼 a590687 的回复:]
引用 4 楼 guosha 的回复:
不是不可以,是优雅不优雅的问题,
就像几十条if语句可以用一个字典结构来替


引用 3 楼 a590687 的回复:
用''' 菜单''' 三引号 不是就可以么

今天又看到这个,要优雅的是不是做GUI发看点啊。pyqt4?
[/Quote]
快乐田伯光 2011-01-07
  • 打赏
  • 举报
回复
这是一个使用这个menu模块的文件:

import os
import grub_util
import menu_util

def query_system_boot_info(menu_path_list):
'''
'''
return grub_util.ShowBootInfo()

def switch_system(menu_path_list):
'''
'''
grub_util.ShowBootInfo()
answer = raw_input('Please enter new default boot item: ')
if answer.isdigit():
boot_index = int(answer)
return grub_util.SetDefaultItem(boot_index)
else:
print 'Input is invalid!'

return 0

system_boot_menu_dict = {
1 : ('Query boot info', query_system_boot_info),
2 : ('Switch to other system', switch_system),
}

def main(menu_path_list):
return menu_util.menu_manage(menu_path_list, system_boot_menu_dict)

if __name__ == '__main__':
pass


快乐田伯光 2011-01-07
  • 打赏
  • 举报
回复
我已经自己写了一个,用它写了一个不小的系统管理菜单,感觉还不错。代码如下:

#!/usr/bin/env python
'''
Description: This is a menu manage module, it take a dictory data struct as a input and output a text menu
Author: Joshua.guo <shijian.guo@bigbandnet.com>
Date: 28/12/2010
'''

def sf():
'''
just a test function
'''
pass

def menu_manage(menu_path_list, menu_dict):
'''
menu_path_list likes below:
menu_path_list = ['1st', '2nd', '3rd']

menu_dict likes below:
menu_dict = {
1 : ('system', 'test.py'),
2 : ('software', 'test.py'),
3 : ('user', function),
4 : ('network', function),
5 : ('1+1 redundancy', 'test.py'),
6 : ('snmp', function),
7 : ('logout', 'test.py'),
}

The output menu likes below:

1st -> 2nd -> 3rd:
1) system
2) software
3) user
4) network
5) 1+1 redundancy
6) snmp
7) logout
Select option number ( b>ack or l>ist ) (b) :
'''

#output menu
output_menu(menu_path_list, menu_dict)
ret = 0
while True:
#output input prompt
print ''
input_str = raw_input('Select option number ( b>ack or l>ist ) (b): ')
if input_str in ['', 'b']:
if len(menu_path_list) == 1:
#it is the root menu, just output this menu again
output_menu(menu_path_list, menu_dict)
continue
else:
#back to top menu
return 6

elif input_str in ['l']:
print ''
output_menu(menu_path_list, menu_dict)
continue

try:
option_number = int(input_str)
except ValueError:
print 'Error, input should be a number!'
continue

if option_number not in menu_dict:
print 'Error, input option is invalid!'
continue

menu_node = menu_dict[option_number][0]
if type(menu_dict[option_number][1]) == type(sf):
#it is a function
sub_menu_path_list = menu_path_list[:]
sub_menu_path_list.append(menu_node)
func = menu_dict[option_number][1]
ret = func(sub_menu_path_list)
else:
#it is a script
script_name = menu_dict[option_number][1]
module_name = script_name[:-3]
exec('import ' + module_name)
sub_menu_path_list = menu_path_list[:]
sub_menu_path_list.append(menu_node)
exec "ret = %s.main(%s)" % (module_name, sub_menu_path_list)

if ret == 6:
#exit from child menu, output parent menu again
output_menu(menu_path_list, menu_dict)
else:
#do nothing
pass

return 0

def output_menu(menu_path_list, menu_dict):
'''
menu_path_list likes below:
menu_path_list = ['1st', '2nd', '3rd']

menu_dict likes below:
menu_dict = {
1 : ('system', 'test.py'),
2 : ('software', 'test.py'),
3 : ('user', function),
4 : ('network', function),
5 : ('1+1 redundancy', 'test.py'),
6 : ('snmp', function),
7 : ('logout', 'test.py'),
}
The output menu likes below:

1st -> 2nd -> 3rd:
1) system
2) software
3) user
4) network
5) 1+1 redundancy
6) snmp
7) logout
'''

#output menu path
menu_path = ' -> '.join(menu_path_list)
print menu_path + ':'

#output menu body
for menu_key in sorted(menu_dict.keys()):
print '\t%d) %s' % (menu_key, menu_dict[menu_key][0])

return 0


notax 2011-01-07
  • 打赏
  • 举报
回复
试试python 的ncurse, (windows上没玩过, 不知道行不行)

>>> import curses
>>>

http://www.ibm.com/developerworks/cn/linux/sdk/python/python-6/index.html
bestdowt1314 2011-01-07
  • 打赏
  • 举报
回复
pyqt4 Menubar.这个行不,做gui开发很方便
加载更多回复(5)

37,743

社区成员

发帖
与我相关
我的任务
社区描述
JavaScript,VBScript,AngleScript,ActionScript,Shell,Perl,Ruby,Lua,Tcl,Scala,MaxScript 等脚本语言交流。
社区管理员
  • 脚本语言(Perl/Python)社区
  • WuKongSecurity@BOB
加入社区
  • 近7日
  • 近30日
  • 至今

试试用AI创作助手写篇文章吧