【问题标题】:Interact with python REPL from python script从 python 脚本与 python REPL 交互
【发布时间】:2019-02-27 05:03:58
【问题描述】:

我想找到(或制作)一个 python 脚本,它逐行读取不同的 python 脚本并打印执行的命令和之后的输出。

假设你有一个 python 脚本,testfile.py 这样:

print("Hello world")

for i in range(3):
    print(f"i is: {i}")

现在,我想要一个解析 testfile.py 并输出以下内容的不同 python 脚本:

print("Hello world")
## Hello world
for i in range(3):
    print(f"i is: {i}")
## i is: 0
## i is: 1
## i is: 2

非常感谢您对现有软件或如何实现此目标的新代码提出任何建议!


尝试/概念代码:

从 python 运行ipython

最初的想法之一是使用subprocess从python运行ipython:

import subprocess
import re
try:
    proc = subprocess.Popen(args=["ipython", "-i"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True)
    # Delimiter to know when to stop reading
    OUTPUT_DELIMITER = ":::EOL:::"
    # Variable to contain the entire interaction:
    output_string = ""
    # Open testfile.py
    with open("testfile.py") as file_:
        for line in file_:
            # Read command
            cmd = line.rstrip()
            # Add the command to the output string
            output_string += cmd + "\n"
            proc.stdin.write(f"{cmd}\n")
            # Print the delimiter so we know when to end:
            proc.stdin.write('print("{}")\n'.format(OUTPUT_DELIMITER))
            proc.stdin.flush()
            # Start reading output from ipython
            while True:
                thisoutput = proc.stdout.readline()
                thisoutput = thisoutput.rstrip()
                # Now check if it's the delimiter
                if thisoutput.find(OUTPUT_DELIMITER) >= 0:
                    break
                output_string += thisoutput + "\n"

except Exception as e:
    proc.stdout.close()
    proc.stdin.close()
    raise
proc.stdout.close()
proc.stdin.close()
print("-" * 4 + "START OUTPUT" + "-" * 4)
print(output_string)
print("-" * 4 + "END OUTPUT" + "-" * 4)

在这种方法中,问题变成了缩进块,例如for 循环。 理想情况下,这样的事情只使用普通的python(而不是ipython)就可以工作。

【问题讨论】:

  • 为什么?最终目标是什么?这个 REPL/interpreter-mimicking-script 有什么好处?
  • @DeepSpace 最终目标是很好地排版 python 脚本。这是第一步。
  • 我用python[code.InteractiveConsole.interact](https://docs.python.org/3/library/code.html#code.InteractiveConsole.interact)方法搞定了。

标签: python-3.x ipython read-eval-print-loop


【解决方案1】:

code.InteractiveConsole.interact 完全按照要求进行。

【讨论】:

    【解决方案2】:

    这不是完全你想要的,但它很接近。 trace 模块做了非常相似的事情。

    so.py:

    print("Hello world")
    for i in range(3):
        print(f"i is: {i}")
    
    python -m trace --trace so.py
    
     --- modulename: so, funcname: <module>
    so.py(1): print("Hello world")
    Hello world
    so.py(3): for i in range(3):
    so.py(4):     print(f"i is: {i}")
    i is: 0
    so.py(3): for i in range(3):
    so.py(4):     print(f"i is: {i}")
    i is: 1
    so.py(3): for i in range(3):
    so.py(4):     print(f"i is: {i}")
    i is: 2
    so.py(3): for i in range(3):
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-29
      • 2023-04-10
      • 1970-01-01
      • 2023-03-09
      • 2021-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多