2015-06-17 81 views
0

我想將用戶輸入表達式輸出爲字符串。如何將Python表達式轉換爲字符串

原因是輸入表達式是用戶定義的。我想輸出表達式的結果,打印出導致這個結果的語句。

import sys 
import shutil 

expression1 = sys.path 
expression2 = shutil.which 

def get_expression_str(expression): 
    if callable(expression): 
     return expression.__module__ +'.'+ expression.__name__ 
    else: 
     raise TypeError('Could not convert expression to string') 

#print(get_expression_str(expression1)) 
# returns : builtins.TypeError: Could not convert expression to string 
#print(get_expression_str(expression2)) 
# returns : shutil.which 

#print(str(expression1)) 
#results in a list like ['/home/bernard/clones/it-should-work/unit_test', ... ,'/usr/lib/python3/dist-packages'] 

#print(repr(expression1)) 
#results in a list like ['/home/bernard/clones/it-should-work/unit_test', ... ,'/usr/lib/python3/dist-packages'] 

我看着Python的檢查模塊,但即使

inspect.iscode(sys.path) 

個返回False

對於那些誰不知道爲什麼它是一個字符串的解析使用functools.partial看到一個表達反parse statement string

背景。

一個程序應該工作。應該,但並不總是如此。因爲程序需要特定的資源,操作系統,操作系統版本,其他軟件包,文件等。每個程序都需要不同的需求(資源)才能正常運行。 需要哪些具體要求無法預測。系統最清楚哪些資源是不可用的。因此,而不是手動檢查所有設置和配置,讓幫助程序爲您做這個。

因此,用戶或程序的開發人員將他的要求與陳述如何檢索此信息一起指定:表達式。哪些可以使用eval執行。可以。就像StackOverflow上提到的eval是邪惡的。 使用eval很難使用黑名單進行安全,請參閱:http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html 使用SO的多個提示我使用帶有字符串的namedtuple與用戶輸入字符串和函數進行比較。

白名單比黑名單更好。只有當解析的表達式字符串匹配「bare_expression」時,纔會返回表達式。 這個白名單包含更多信息如何處理f.e. 「unit_of_measurement」。它解釋了什麼和爲什麼,但這是必要的。所述namedtuples列表得多,不只是一個白名單,並且被定義:

Expr_UOfM = collections.namedtuple('Expr_UOfM', ['bare_expression', 'keylist', 'function', 'unit_of_measurement', 'attrlist']) 

匹配(非常有限的)列表,它的namedtuple:

Exp_list = [Expr_UOfM('sys.path', '' , sys.path, un.STR, []), 
      Expr_UOfM('shutil.which', '', shutil.which, None, [])] 

該列表可以是非常長且內容對於進一步正確處理至關重要。請注意,第一個和第三個字段非常相似。應該有一個單一的參考點,但對我而言,這是不可能的。注意字符串:'sys.path'等於用戶輸入(的一部分),並且表達式:sys.path是namedtuple列表的一部分。良好的分離,限制可能的濫用。 如果字符串和表達式不是100%相同的,可能會發生很難調試的怪異行爲。 所以它想要使用get_expression_str函數檢查第一個和第三個字段是否相同。只是爲了提高 程序的總健壯性。

我使用Python 3.4

+0

嘗試'str(表達式)' – SomethingSomething

+0

我這樣做了,從底部看4e行,但沒有成功。 – Bernard

+0

那麼用戶的輸入在哪裏?你是不是用一個字符串(例如''sys.path'')開始*? – jonrsharpe

回答

0

爲什麼不使用eval

>>> exp1 = "sys.path" 
>>> exp2 = "[x*x for x in [1,2,3]]" 
>>> eval(exp1) 
['', 'C:\\Python27\\lib\\site-packages\\setuptools-0.6c11-py2.7.egg', 'C:\\Pytho 
n27\\lib\\site-packages\\pip-1.1-py2.7.egg', 'C:\\Python27\\lib\\site-packages\\ 
django_celery-3.1.1-py2.7.egg', 'C:\\Python27\\lib\\site-packages\\south-0.8.4-p 
y2.7.egg', 'C:\\Windows\\system32\\python27.zip', 'C:\\Python27\\DLLs', 'C:\\Pyt 
hon27\\lib', 'C:\\Python27\\lib\\plat-win', 'C:\\Python27\\lib\\lib-tk', 'C:\\Py 
thon27', 'C:\\Python27\\lib\\site-packages', 'C:\\Python27\\lib\\site-packages\\ 
PIL'] 
>>> eval(exp2) 
[1, 4, 9] 
+0

我的意思與eval相反。 eval輸入是一個字符串,輸出是一個表達式。我想輸入一個表達式並輸出一個字符串。所以在你的例子中[1,4,9]返回exp2在我看來,這是不可能的。順便說一句eval是非常危險的使用,這就是我使用functools.partial的原因 – Bernard

+0

這似乎是不可能的。我不知道使用場景是什麼。如果您正在解析python代碼,請考慮使用ast。 – NeoWang

+0

我期待ast,但找不到解決方案。你可以使用ast模塊爲sys.path創建一些代碼嗎? – Bernard

相關問題