2015-11-25 45 views
1

比方說,我有一些Python代碼串獲得價值exec`叫

code = """ 
a = 42 
a 
""" 

和我exec的代碼串:

result = exec(code) 

然後result總是會None。是否有任何方法來獲得最後一個表達式的值?在這種情況下,這將是5,因爲a是最後一個表達式。

編輯:這是我問的功能的另一個例子。比方說,我們有Python代碼(存儲在變量code

a = 100 
sqrt(a) 

那我怎麼才能在這樣的方式,讓我結果10執行代碼 - 也就是說,sqrt(a)

編輯編輯:另一個例子:我想exec代碼

function_a() 
function_b() 
function_c() 

有什麼辦法,我可以定義某種magic_exec功能,使

magic_exec(code) 

會爲我提供價值function_c()

+0

這裏很有可能你有一個[XY問題](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)。 – TigerhawkT3

+0

我不這麼認爲。我的問題是我希望能夠「看到」任意Python代碼的執行結果。什麼'exec'給我('None')沒有用於這個目的。我想要一個有用的價值。 – feralin

+0

執行任意Python代碼甚至不一定會產生結果。例如,'exec('pass')'。你是出於好奇,還是在爲一個實際的程序制定算法? – TigerhawkT3

回答

0
exec('a = 4') 
print a % prints 4 

>>> code = """ 
... a = 42 
... b = 53""" 
>>> exec(code) 
>>> a 
42 
>>> b 
53 

或者,如果你說你不知道的最後一件事爲b,例如,那麼你可以有這樣的:

code = """ 
a = 4 
b = 12 
abc_d=13 
""" 
t = re.findall(r'''.*?([A-Za-z0-9_]+)\s*?=.*?$''', code) 
assert(len(t)==1) 
print t[0] % prints 13 
+0

看我的編輯。如果我有一個正在評估的任意表達式,該怎麼辦?我如何從'exec'調用中獲得它的價值? – feralin

+0

我認爲你仍然沒有看到我所得到的 - 如果我的問題不清楚,我很抱歉。假設我根本沒有變量賦值。我在我正在評估的代碼中只有兩個函數調用('a()\ n b()')。我如何定義一些'magic_exec'函數來運行'a()'和'b()'_然後給我'b()'而不是'None'的value_值? – feralin

0

這不會讓你最後的評估值,但獲得了整個本地變量列表。

>>> loc = {} 
>>> exec(code, {}, loc) 
>>> loc 
{'a': 42} 
+0

我知道我可以訪問'exec'調用中定義的變量。假設評估的最後一個表達式不僅僅是一個變量。如果最後一個表達式是'sqrt(4)',我希望接收'2'而不是'None'。這就是我所問的。 – feralin

0

說實話,我不能說我很高興與此有關。這感覺很不好,我還沒有測試過這一切。另一方面,我對此很滿意。這很有趣。無論如何,希望這可以幫助你,或者至少接近你想要的。 locals()給出了一個詞典,以便輸出列表順序與第一個eval失敗的項目的輸入順序不匹配。如果您不想要​​3210作爲分隔符,則可以將其更改爲'\n'

import math 

def magic_exec(_command): 
    _command = _command.split(';') 
    _result = None 
    _before = list(locals()) # Get list of current local variables 

    for _code in _command: 
     _code = _code.strip() # .strip() prevent IndentationError 
     try: 
      if eval(_code) != None: # For functions with no return 
       _result = eval(_code) 
     except (NameError, SyntaxError): 
      try: 
       _before = list(locals()) 
       exec(_code) 
      except NameError as e: # For undefined variables in _command 
       print("An Error Occurred with line ' {0} ' as was skipped: {1}".format(_code, e)) 

    del _code # delete temp var _code 
    # Get new list of locals that didn't exist at the start 
    _after = [val for val in list(locals()) if val not in _before] 

    if _after: 
     return eval(_after[0]) 
    else: 
     return _result 

#Dummy class and functions 
class Class1(object): 
    def __init__(self, x): 
     self._x = x 

    def get_val(self): 
     return self._x 

    def __repr__(self): 
     return type(self).__name__ 

def func1(x): 
    return x + x 

def func2(x): 
    print(x*x) 

if __name__ == '__main__': 
    code = \ 
""" 
a = 42; a; v; y = 2; b = func1(5); s = 'Hello'; func2(10); c = 25; l = []; l.append('Value'); 
t = math.sqrt(c); pass; 20*10; print('TEST'); math.sqrt(c); d = Class1('World'); d.get_val(); 
def func3(x): return x ** 2; s = func3(15) 
""" 
    values = magic_exec(code) 
    print(values) 
+0

我喜歡這個主意,但有很多併發症。如果命令沒有用分號隔開怎麼辦?如果代碼中有分號(如註釋或字符串),那麼這些分號無法分離命令呢?我跳得比自己處理Python AST更簡單,但我認爲你的解決方案只適用於相對簡單的情況。 – feralin

+0

即使行被換行符和/或分號隔開,我認爲您所做的解析類型(拆分換行符/分號)可輕鬆破解工作代碼。 – feralin

+0

你真的會傳遞評論嗎?我不認爲你可以。 ';'分隔符的分割與python中的一樣,一行新的代碼可以用';'表示。如果在字符串中使用分號,它會中斷。用';'分隔這也是一個限制。你可以使用'\ n'假設你把它正確地分隔開來,但它又用'\ n'分隔字符串char –

0

該請求當然是有效的,因爲我在創建基於Python的環境期間也需要這樣的函數。我解決了這個問題,下面的代碼利用了Python AST機制:

def my_exec(script, globals=None, locals=None): 
    '''Execute a script and return the value of the last expression''' 
    stmts = list(ast.iter_child_nodes(ast.parse(script))) 
    if not stmts: 
     return None 
    if isinstance(stmts[-1], ast.Expr): 
     # the last one is an expression and we will try to return the results 
     # so we first execute the previous statements 
     if len(stmts) > 1: 
      exec(compile(ast.Module(body=stmts[:-1]), filename="<ast>", mode="exec"), globals, locals) 
     # then we eval the last one 
     return eval(compile(ast.Expression(body=stmts[-1].value), filename="<ast>", mode="eval"), globals, locals) 
    else: 
     # otherwise we just execute the entire code 
     return exec(script, globals, locals) 

的代碼應該是相當不言自明的,基本上

  1. 腳本分成多個語句
  2. 如果最後一個是表達式,執行第一部分作爲語句,最後一部分作爲表達式。
  3. 否則執行整個腳本作爲語句。