我试图构建一个CLI,直到用户决定退出为止。CLI的功能是能够在程序运行时通过在终端中键入命令来探索json文件。
现在,命令是根据if/else语句进行检查的,但我想添加一下,以便以argparse模块的方式检查命令,但不知道在程序运行时是如何完成的。因为我无法理解这一点,所以类方法被映射到特定的命令,并在指定命令时执行,而不必依赖于if/else逻辑。
最大的问题不是像-v那样的单个命令,因为它们很容易映射到带有dict的函数。但是,在-v LEAGUE命令中,LEAGUE或-d LEAGUE SEASON TYPE在不创建大型字典的情况下很难映射,因为参数可能会有所不同。任何关于如何改进的建议都是非常感谢的!
import os
import sys
class CLIStats:
def __init__(self):
"""Displays the welcome screen and loads the season-params.json
which contains the avalible leagues and their seasons that
can be downloaded. Pickled with pre-proccessed IDs is also loaded.
"""
self.header = self.header()
self.description = self.description()
self.commands = self.commands()
self.leagues = {'EN_PR': ['2019/2020', '2018/2019', '2017/2018', '2016/2017'],
'EU_CL': ['2019/2020', '2018/2019', '2017/2018', '2016/2017'],
'ES_PL': ['2019/2020', '2018/2019', '2017/2018', '2016/2017']}
@staticmethod
def header():
"""Display's welcome message"""
os.system('clear')
print('\t','*'*60)
print("\t\t*** Welcome - Football Stats generator ***")
print('\t','*'*60)
@staticmethod
def description():
"""Display's short description"""
print('Interface to download: \t playerstats \t fixturestats \t team standing \n')
print('Type "exit" to terminate shell')
@staticmethod
def commands():
"""Display's avalible commands and how to use them"""
commands = {'View Leagues': '-v',
'View League Seasons': '-v LEAGUE',
'Download stats': '-d LEAGUE SEASON TYPE',
'Help' : '-h',}
for key, value in commands.items():
print("{: <25} {}".format(key, value))
print('\n')
def view_leagues(self):
"""Prints out leagues in self.leagues"""
for league in self.leagues.keys():
print("{: <10}".format(league), end="")
print('\n')
def view_seasons(self, league):
"""Prints seasons for a league in self.leagues"""
if league in self.leagues:
seasons = self.leagues[league]
print(league,'seasons:')
for season in seasons:
print("{: <20}".format(season), end="")
print('\n')
else:
print(league, 'is not avalible')
print('\n')
def view_league_args(self):
"""Creates a list with set of args that can be passed
by user to execute view_league()"""
args = []
for league in self.leagues.keys():
args.append('-v' + ' ' + league)
return args
def main():
"""Runs the interface"""
interface = CLIStats()
cmd = {'-v': interface.view_leagues,
'exit': sys.exit,
'View Stats Type': '-s',
'-h' : 'interface.help', }
while True:
usr_command = input('CLIStats$ ')
if usr_command in cmd.keys():
cmd.get(usr_command)()
elif usr_command in interface.view_league_args():
league = usr_command.split(' ')[-1]
interface.view_seasons(league)
elif len(usr_command.split(' ')) == 4:
league = usr_command.split(' ')[1]
season = usr_command.split(' ')[2]
stat_type = usr_command.split(' ')[3]
interface.download_stats(league, season, stat_type)
else:
if usr_command.split(' ')[0] not in cmd.keys():
print('Command not valid')
else:
print('Could not find the specified params')
if __name__ == '__main__':
main()发布于 2020-04-24 07:00:08
虽然argparse()可能被滥用来提供一些所需的功能,但它不是正确的工具。例如,它设计为在检测到错误时退出,例如无法识别的命令或缺少参数。
标准库中的cmd是一个更好的工具。编写命令解释器就像编写cmd.Cmd的子类和为每个命令定义"do_command“方法一样简单,例如do_view()、do_download()等。下面是一个基于代码的示例,但是"do_command()”方法只是打印一些东西。
import cmd
class StatShell(cmd.Cmd):
intro = '\n'.join([
"\t" + "*"*60,
"\t\t*** Welcome - Football Stats generator ***",
"\t" + "*"*60,
"",
"\tType help or ? to list commands,",
"\t\tor help command to get help about a command."
])
prompt = "CLIStats: "
def do_download(self, arg):
"""Download statistics: download LEAGUE SEASON TYPE"""
arg = arg.split()
if len(arg) == 3:
league, season, type = arg
print(f"downloading {league} {season} {type}")
else:
self.error("bad 'download' command.")
def do_exit(self, arg):
"""Exit the interpreter."""
print("exiting ...")
return True
def do_view(self, arg):
"""view leagues or seasons: view [LEAGUE] """
if arg:
league = arg[0]
print(league,'seasons: ...')
else:
print('leagues ...')
def main():
StatShell().cmdloop()发布于 2020-04-23 22:58:13
这是:
self.leagues = {'EN_PR': ['2019/2020', '2018/2019', '2017/2018', '2016/2017'],
'EU_CL': ['2019/2020', '2018/2019', '2017/2018', '2016/2017'],
'ES_PL': ['2019/2020', '2018/2019', '2017/2018', '2016/2017']}看上去太过分了。充其量,您需要存储:
int的最小和最大年数{'EN_PR', 'EU_CL', 'ES_PL'}其他的一切都可以衍生出来。
Display's avalible commands and how to use them至
Displays available commands and how to use them和
is not avalible至
is not available args = []
for league in self.leagues.keys():
args.append('-v' + ' ' + league)
return args 可以是
return ' '.join(f'-v {league}' for league in self.league_names)假设league_names持有前面描述的集合。
https://codereview.stackexchange.com/questions/241099
复制相似问题