设计像交互式shell一样的python

Design python like interactive shell

本文关键字:一样 python 交互式 shell      更新时间:2023-10-16

interactive shell一样的python背后的设计模式是什么?我想为我的服务器执行此操作,但我最终会得到很多if - then- else模式。

例如,当我开始python interpreter时,我得到这样的东西

Python 2.6.7 (r267:88850, Feb  2 2012, 23:50:20)
[GCC 4.5.3] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> help
帮助

后,提示更改为帮助

Welcome to Python 2.6!  This is the online help utility.
If this is your first time using Python, you should definitely check out
the tutorial on the Internet at http://docs.python.org/tutorial/.
Enter the name of any module, keyword, or topic to get help on writing
Python programs and using Python modules.  To quit this help utility and
return to the interpreter, just type "quit".
To get a list of available modules, keywords, or topics, type "modules",
"keywords", or "topics".  Each module also comes with a one-line summary
of what it does; to list the modules whose summaries contain a given word
such as "spam", type "modules spam".
help>

我认为这是read-eval loop设计之王。

对于 REPL,您需要一个上下文(存储 REPL 状态的对象)、一个命令解析器(解析输入并生成 AST)以及一种将命令映射到操作的方法(操作通常只是修改上下文和/或产生副作用的函数)。

一个简单的 REPL 可以像下面这样实现,其中上下文是使用简单的字典实现的,AST 只是在空格上拆分的输入命令,字典用于将命令映射到操作:

context = {}
commands = {}
def register(func):
    """ convenience function to put `func` into commands map """
    # in C++, you cannot introspect the function's name so you would
    # need to map the function name to function pointers manually
    commands[func.__name__] = func
def parse(s):
    """ given a command string `s` produce an AST """
    # the simplest parser is just splitting the input string,
    # but you can also produce use a more complicated grammer
    # to produce a more complicated syntax tree
    return s.split()
def do(cmd, commands, context):
    """ evaluate the AST, producing an output and/or side effect """
    # here, we simply use the first item in the list to choose which function to call
    # in more complicated ASTs, the type of the root node can be used to pick actions
    return commands[cmd[0]](context, cmd)
@register
def assign(ctx, args):
    ctx[args[1]] = args[2]
    return '%s = %s' % (args[1], args[2])
@register
def printvar(ctx, args):
    print ctx[args[1]]
    return None
@register
def defun(ctx, args):
    body = ' '.join(args[2:])
    ctx[args[1]] = compile(body, '', 'exec')
    return 'def %s(): %s' % (args[1], body)
@register
def call(ctx, args):
    exec ctx[args[1]] in ctx
    return None
# more commands here
context['PS1'] = "> "
while True:
    # READ
    inp = raw_input(context["PS1"])
    # EVAL
    cmd = parse(inp)
    out = do(cmd, commands, context)
    # PRINT
    if out is not None: print out
    # LOOP

示例会话:

> assign d hello
d = hello
> printvar d
hello
> assign PS1 $
PS1 = $
$defun fun print d + 'world'
def fun(): print d + 'world'
$call fun
helloworld

通过更多的技巧,您甚至可以将上下文和命令字典合并在一起,从而允许在 shell 的语言中修改 shell 的命令集。

这个设计模式的名称,如果它有一个名字,是Read-Eval-Print Loop设计模式;所以是的,你的问题有点回答自己。