2016-01-15 51 views
3

我想將函數定義傳遞給python命令行腳本。做這個的最好方式是什麼?我使用python 2.假設我有一個這樣的腳本:如何將函數定義傳遞給python腳本作爲字符串

#myscript.py 
x = load_some_data() 
my_function = load_function_definition_from_command_line() 
print my_function(x) 

,我想這樣稱呼它:python myscript.py 'def fun(x): return len(x)'

我如何執行load_function_definition_from_command_line一部分?

我想一個解決辦法:

  1. 得到命令行字符串函數定義
  2. 它寫在一些臨時目錄
  3. 負載使用的解決方案從文件中定義的.py擴展名的文件這個問題:How to import a module given the full path?
  4. 執行
  5. 清理

但我確定必須有更好的方法。

+1

我想你調用代碼應該解釋你爲什麼要傳遞一個函數作爲一個字符串來運行的原因。這可以幫助我們更好地幫助你,並且可能找到一種解決方法來使用當前答案所提示的內容(eval和exec)。評估命令行參數並將其作爲代碼運行極其危險,除非絕對必要,否則不應該完成。 – disflux

+0

出於好奇 - 你爲什麼需要這個?我問,因爲它導致非常糟糕的解決方案(eval),也許你只是沒有看到其他的可能性。 –

+0

我正在編寫一個shell應用程序,用於對來自其他應用程序的日誌/輸出進行map/reduce/filter操作 –

回答

2

您可以使用eval來運行在字符串中定義的代碼。像這樣:

import sys 

x = load_some_data() 
function = eval("".join(sys.argv[1:])) 
print(function(x)) 

有了您的具體的例子,雖然你可能需要使用像lambda x: len(x)

正如@揚Spurny正確地指出:「永遠,永遠,永遠不會,除非你是絕對的把握使用eval別無他法,即使這樣,你也應該停下來思考一下。「

在我看來,更好的策略是將數據加載器和執行器變成一個模塊,其方法是將函數作爲參數並運行所需的代碼。最終的結果是這樣的:

import data_loader_and_executor 

def function(x): 
    return len(x) 

data_loader_and_executor.run(function) 
+1

I強烈建議做最後一句('理想情況下,不應該永遠不要使用eval'。'')更明顯(粗體)或改寫它,例如:「永遠,永遠不會使用'eval',除非你絕對**確定沒有別的辦法,即使如此,你應該停下來再想一想。「 –

+0

eval背後的危險是什麼? –

+2

@JanOsch - 有人可以通過任何**任何**,它會被執行。例如,一些小丑可以通過:「def f(x):import shutil; shutil.rmtree('/');」並刪除你的文件系統。 Eval是您程序中最大的最危險的後門程序。 –

0

使用功能exec

import sys 

def load_function_definition_from_command_line(): 
    exec(sys.argv[1]) 
    return locals()['fun'] 

當然,你要知道,你的功能將如何命名,但是這可以通過傳遞到你的論點第二完成參數:

$ python myscript.py 'def fun(x): return len(x)' fun 

然後你的函數看起來像:

import sys 

def load_function_definition_from_command_line(): 
    exec(sys.argv[1]) 
    return locals()[sys.argv[2]] 

!!請記住,評估用戶輸入是非常危險的!

編輯:由於fun將是locals定義的唯一對象,你可以只返回第一個元素locals()

def load_function_definition_from_command_line(): 
    exec(sys.argv[1]) 
    return locals()[0] 
0

您可以使用eval或exec在當前的命名空間創建一個函數。您的環境中

exec "somefunc(x): return x * 2" 
somefunc(2) # 2 

python load_function.py "def f(x): return x * 2"

//load_function.py 
import sys 

exec sys.argv[1] 
print f(2) 

命令行輸出:
4

編輯:強制性的,「這是不明智的執行用戶的輸入像這個。」

相關問題