在shell中逐行运行Python脚本vs原子运行
我正在将MicroPython集成到微控制器中,我想向我的产品(通过与PC的连接)添加一个调试逐步执行模式 谢天谢地,MicroPython包含了一个REPLakapythonshell功能:我可以一次输入一行代码并执行 我想使用此功能在PC端单步执行,并在Python脚本中一行一行地发送 一次运行一行Python脚本与在shell中逐行运行Python脚本vs原子运行,python,micropython,Python,Micropython,我正在将MicroPython集成到微控制器中,我想向我的产品(通过与PC的连接)添加一个调试逐步执行模式 谢天谢地,MicroPython包含了一个REPLakapythonshell功能:我可以一次输入一行代码并执行 我想使用此功能在PC端单步执行,并在Python脚本中一行一行地发送 一次运行一行Python脚本与Python my_script.py之间除了可能的时间安排之外,还有什么区别吗 有什么不同吗 对 例如,下面的代码在.py文件中工作,但在交互式解释器中是一个SyntaxErr
Python my_script.py
之间除了可能的时间安排之外,还有什么区别吗
有什么不同吗
对
例如,下面的代码在.py
文件中工作,但在交互式解释器中是一个SyntaxError
:
x = 1
if x == 1:
pass
x = 2
还有很多不同之处,但仅此一点就足以吓跑你 我不知道MicroPython是否内置了compile()和exec()。 但是,当嵌入式Python拥有它们并且MCU拥有足够的RAM时,我会执行以下操作:
def foo(): # 1
for i in range(10): # 2
if i == 5: # 3
raise Exception("Argh!") # 4
# 5
foo() # 6
是的,有区别。正如在另一个答案中所解释的,逐行执行可能很棘手。因此,代码块是您最好的选择。在stdin上一次传递一行代码是一种完全不可接受的替代调试器的方法 假设您要调试以下内容:
def foo(): # 1
for i in range(10): # 2
if i == 5: # 3
raise Exception("Argh!") # 4
# 5
foo() # 6
…在适当的分步调试器中,用户可以这样使用它:
break 4
run
现在,你打算怎么做?如果在REPL中输入函数,则函数定义为一个操作,并作为一个操作运行。它不停在6号线。它不允许你一行一行地进行。for
循环也是如此:每次输入for
循环的文本一行,不允许在引发异常之前对其进行单步处理
如果消除函数并消除循环(生成代码
\u something=iter(范围(10));i=\u something.next()
,可能?),则需要模拟作用域的效果。这意味着你的语言与你所谓的“调试”语言截然不同;为什么你的例子在shell中失败了?很复杂。你真的不需要了解,我想了解,这样我就可以确定这是否只是几个角落的案子,而不仅仅是几个角落的案子。您应该找到一种更好的方法来编写调试器,例如使用@wim,……不幸的是,它看起来像是sys.settrace()
在micropython中不可用,例如。这并不意味着我支持OP提议的黑客行为,而不是正确地实现必要的VM支持。假设你有一个循环。您是否打算让自己的解释器管理流控制?因为否则,你不能一次跨一行——要么整个循环运行,要么一行都不运行。实际上,这意味着你需要更多的东西才能获得单步执行的效果:实际上,你需要在可能设置断点的任何位置注入新的函数调用。可以想象通过插入代码(理想情况下,解析并以编程方式修改AST)来实现这一点,但这将是一个糟糕的局面,我不理解这样一句话:一次输入for循环的文本一行,不允许在抛出异常之前进行步进。
Nvm我明白了:这是整个流控制问题。对,对。一旦调用foo()
,所有foo
都会运行,它不会一次运行一行。如果我向它发送代码块呢?i、 e.如果块,对于块,等等(1)这意味着您需要模拟在代码上输入和离开函数作用域的所有影响(这些影响并不总是明显的),以及(2)块仍然一次运行,而不是一行一行。如果我做了代码块,这将绕过提到的问题?应该这样做。但是,如果您正在逐块执行,那么在引发异常时,您必须不断更正行号。如果您真的想一个命令一个命令地执行所有命令并跟踪整个过程,恐怕您没有其他选择,只能获取代码,使用AST,在每个命令进入AST后调用添加的跟踪函数,编译AST,然后将字节码发送给MCU并运行它。这并不像听起来那么难实现。