2014-08-28 42 views
2

我有一個包含Python語句的文件,我想以這種方式運行Python,以便打印到stdout,如果這些命令在REPL中運行,將顯示什麼內容。將命令放入Python REPL

例如,如果該文件是

1 + 4 
'a' + 'b' 

然後輸出應該是

>>> 1 + 4 
5 
>>> 'a' + 'b' 
'ab' 

有沒有辦法做到這一點?

+1

Windows? * n * x?跨平臺? – 2014-08-28 21:05:37

+0

Linux,但我真的希望有一個跨平臺的方法。 – 2014-08-28 21:25:43

回答

3

您可以使用從pexpectreplwrap要實現這一目標,甚至有一個python方法:

from pexpect import replwrap 

with open("commands.txt", "r") as f: 
    commands = [command.strip() for command in f.readlines()] 

repl = replwrap.python() 
for command in commands: 
    print ">>>", command 
    print repl.run_command(command), 

將返回:

python replgo.py 
>>> 1 + 4 
5 
>>> 'a' + 'b' 
'ab' 

你需要獲得最新版本的pexpect。

2

一些AST魔法可以幫助在這裏:

import ast 
import itertools 


def main(): 
    with open('test.txt', 'r') as sr: 
     parsed = ast.parse(sr.read()) 
     sr.seek(0) 
     globals_ = {} 
     locals_ = {} 
     prev_lineno = 0 
     for node in ast.iter_child_nodes(parsed): 
      source = '\n'.join(itertools.islice(sr, 0, node.lineno - prev_lineno))[:-1] 
      print('>>> {}'.format(source)) 
      if isinstance(node, ast.Expr): 
       print(eval(source, globals_, locals_)) 
      else: 
       exec(source, globals_, locals_) 
      prev_lineno = node.lineno 

if __name__ == '__main__': 
    main() 

輸入:

1 + 4 
'a' + 'b' 
a = 1 
a 

輸出:

>>> 1 + 4 
5 
>>> 'a' + 'b' 
ab 
>>> a = 1 
>>> a 
1 

這裏做的事情是找到每個起始和終止行號通過使用ast模塊解析源,然後調用evalexec,具體取決於它是聲明還是表達式。

上下文保存在globals_locals_

您可以通過使用一些python沙盒來執行evalexec以更安全。

3

(不那麼)快速(大部分)髒了,用code模塊:

import sys 
import code 

infile = open('cmd.py') 
def readcmd(prompt): 
    line = infile.readline() 
    if not line: 
     sys.exit(0) 

    print prompt,line.rstrip() 
    return line.rstrip() 

code.interact(readfunc=readcmd) 

很多需要改進的地方,但它的晚在這裏。不管怎麼說,例如:

sh$ cat cmd.py 
1 + 4 
'a' + 'b' 

1/0 

def f(x): 
    return x*2 

f(3) 
sh$ python console.py 
Python 2.7.3 (default, Mar 13 2014, 11:03:55) 
[GCC 4.7.2] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
(InteractiveConsole) 
>>> 1 + 4 
5 
>>> 'a' + 'b' 
'ab' 
>>> 
>>> 1/0 
Traceback (most recent call last): 
    File "<console>", line 1, in <module> 
ZeroDivisionError: integer division or modulo by zero 
>>> 
>>> def f(x): 
...  return x*2 
... 
>>> f(3) 
6 
0

您可以將輸入管道輸入到pythons「code」模塊。它會顯示輸出,但不會顯示輸入。

$ echo '1 + 1' | python -m code 
Python 2.7.10 (v2.7.10:15c95b7d81dc, May 23 2015, 09:33:12) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
(InteractiveConsole) 
>>> 2