我正在尝试在python中创建python 3 IDE和文本编辑器以了解有关tkinter
的更多信息。在其中(因为它是IDE(,我正在尝试运行用户输入的代码。我能找到的最好的方法是使用exec()
。这有效,如下面的空闲所示:
>>> exec(input('PROMPT: '))
PROMPT: print('Hello World') #Entered in by user, this could be anything.
Hello World # <-- Output
然而,exec()
功能知道它的周围环境。
>>> important_variable = 'important value' #Say that this is important.
>>> exec(input('PROMPT: '))
PROMPT: important_variable = 'meaningless value' #In the IDE, user unknowingly re-assigns to a meaningless value
>>> important_variable #look at the value
'meaningless value' #Yes, the value was changed.
这不是我想要的。我不想连接到主程序,除了我输入的值。(例如,将sys.stdin
、sys.stdout
和sys.stderr
值更改为tkinter
GUI(
我的想法是使用exec()
函数的扩展使用(为您带来help()
(:
exec(source, globals=None, locals=None, /)
Execute the given source in the context of globals and locals.
The source may be a string representing one or more Python statements
or a code object as returned by compile().
The globals must be a dictionary and locals can be any mapping,
defaulting to the current globals and locals.
If only globals is given, locals defaults to it.
我试图对全局变量使用一个空的字典,我将当地人留空。乍一看,这似乎有效。
>>> important_variable = 'important value'
>>> exec_globals = {} #create a black dict of globals
>>> exec(input('PROMPT: '), exec_globals) #pass in the blank dict
PROMPT: important_variable = 'meaningless value' #change to value?
>>> important_variable #look at the value
'important value' #value is kept!
但是,运行代码的程序在异常中可见:
>>> exec_globals = {} #create a black dict of globals
>>> exec(input('PROMPT: '), exec_globals) #pass in the blank dict
PROMPT: THIS SHALL CAUSE A ERROR!
Traceback (most recent call last):
File "<pyshell#288>", line 1, in <module>
exec(input('PROMPT: '), exec_globals) # <-- YOU CAN SEE THE CODE
File "<string>", line 1
THIS SHALL CAUSE A ERROR!
^
SyntaxError: invalid syntax
如何防止这种情况发生并删除与程序的任何连接,从用户输入的代码中看到。但是,我仍然希望在程序中进行一些控制,例如更改sys.stdin
,sys.stdout
和sys.stderr
的值。exec(source, blank_dict)
是要走的路,还是有更好的方法?
经过大量的挖掘,我找到了问题的答案。
答案在code
模块中。正如代码模块上的 python 文档所述:
代码模块提供了在 Python 中实现读取-评估-打印循环的工具。
基本上是模拟代码运行的工具。代码模块提供的函数不仅有助于读取-评估-打印循环,而且还可以在不连接到主程序的情况下运行代码。以这个名为runcode.py
的程序为例:
import code
important_variable = 'important value'
program = 'n'.join([
'for n in range(10):',
' print(n)',
'important_variable = None',
'def error(): raise Exception()',
'error()',
])
interpreter = code.InteractiveInterpreter()
interpreter.runsource(program, '<FAKE MEANINGLESS FILE NAME>', 'exec')
print()
print(important_variable)
输出以下内容:
0
1
2
3
4
5
6
7
8
9
Traceback (most recent call last):
File "<FAKE MEANINGLESS FILE NAME>", line 5, in <module> #No connection!
File "<FAKE MEANINGLESS FILE NAME>", line 4, in error #No connection!
Exception
important value
如果要从实际文件读取,请将'<FAKE MEANINGLESS FILE NAME>'
替换为该文件的绝对路径。这将为您提供更高级的回溯(错误消息将包括在线内容(
最棒的是,这适用于设置和结束脚本,如下所示:
import code
program = 'n'.join([
'for n in range(10):',
' print(n)',
'def error(): raise Exception()',
'error()',
])
interpreter = code.InteractiveInterpreter()
#Setup code. This could change sys.stdin, stdout, etc. and setup variables!
interpreter.runsource('setup_stuff = None', 'whatever name you want', 'exec')
#Run code
interpreter.runsource(program, '<FAKE MEANINGLESS FILE NAME>', 'exec')
#Process Code now that the program is done, this might get the values in local() or something like that.
interpreter.runsource(program, 'whatever name you want', 'exec')
就是这样!