本博客已搬家至我的網站 在路上 - On the way 下面的 技術 分類。html
你能夠經過點擊 更新帖子 【已解決】Python中,用eval強制將字符串轉換爲字典變量時候出錯:NameError: name 'null' is not defined 找到當前帖子的新地址。python
----------------------------------搬家聲明--------------------------------------web
【已解決】Python中,用eval強制將字符串轉換爲字典變量時候出錯:NameError: name 'null' is not definedexpress
【背景】json
在python中,對於一個已經存在的字符串:安全
{ ...,ide "title":「」, }fetch |
其內容的形式很相似於字典類型的變量,因此,但願去將其強制轉換爲字典類型變量,以便於後續處理。
後來找到了介紹,說是用eval強制轉換便可。而後去試了,用了eval去轉換,發現的確是能夠的。
可是,後來去用eval強制轉換另外別的一個字符串:
{ ..., "title":null, } |
卻出現錯誤:
Traceback (most recent call last): File "D:\tmp\WordPress\Others\to_wp\hi-baidu-mover_v2\hi-baidu-mover_v2.py", line 446, in <module> main() File "D:\tmp\WordPress\Others\to_wp\hi-baidu-mover_v2\hi-baidu-mover_v2.py", line 384, in main i=fetchEntry(permalink,datetimepattern,mode) File "D:\tmp\WordPress\Others\to_wp\hi-baidu-mover_v2\hi-baidu-mover_v2.py", line 98, in fetchEntry cmt_err_msg = eval(cmt_soup_uni_removeHtmlTag) File "<string>", line 1, in <module> NameError: name 'null' is not defined |
【解決過程】
1. 網上找了半天,只是看到不少解釋,說是最好有節制的使用,儘可能少用eval函數,其好像存在一些安全隱患。
推薦使用ast模塊。可是ast是python 2.6中才有,而我裝得正好只是python 2.5,暫時不方便從新安裝升級爲2.6,因此繼續折騰,看看eval轉換爲什麼會出現這個錯誤。
2.後來經過google搜索到這個:
Running JSON through Python's eval()? - Stack Overflow
「So, as I'm working with Python 2.4 (i.e. no json module), eval() is ... out by SilentGhost: eval doesn't handle true -> True, false -> False, null -> None correctly. ... line 1, in <module> NameError: name 'false' is not defined 」
其中,注意到其解釋說,eval不支持null,true,false等,無法正確轉換爲None,True,False等,因此,才明白,此處的錯誤,是因爲上面的字符串中,包含了「title」:null,eval函數沒法正確解析,因此報錯「NameError: name 'null' is not defined」。
知道了這個緣由後,那就明白了,無法繼續再用eval了,只有想辦法升級python到2.6+的版本了,而後用
ast.literal_eval
去取代eval,便可。
3。剛又找到官方的解釋:
http://docs.python.org/library/functions.html#eval
eval(expression[, globals[, locals]])? The arguments are a string and optional globals and locals. If provided,globals must be a dictionary. If provided, locals can be any mapping object. Changed in version 2.4: formerly locals was required to be a dictionary. The expression argument is parsed and evaluated as a Python expression (technically speaking, a condition list) using the globals and localsdictionaries as global and local namespace. If the globals dictionary is present and lacks ‘__builtins__’, the current globals are copied into globalsbefore expression is parsed. This means that expressionnormally has full access to the standard __builtin__ module and restricted environments are propagated. If the locals dictionary is omitted it defaults to theglobalsdictionary. If both dictionaries are omitted, the expression is executed in the environment where eval() is called. The return value is the result of the evaluated expression. Syntax errors are reported as exceptions. Example:
>>>
>>> x = 1 >>> print eval('x+1') 2 This function can also be used to execute arbitrary code objects (such as those created by compile()). In this case pass a code object instead of a string. If the code object has been compiled with 'exec' as themode argument, eval()‘s return value will be None. Hints: dynamic execution of statements is supported by the execstatement. Execution of statements from a file is supported by theexecfile() function. The globals() andlocals() functions returns the current global and local dictionary, respectively, which may be useful to pass around for use by eval() or execfile(). See ast.literal_eval() for a function that can safely evaluate strings with expressions containing only literals. |
【總結】
(1)之後安裝python儘可能裝python的新版本,至少是>=2.6,由於其支持ast模塊。
(2)之後儘可能少用eval函數,用ast.literal_eval取代eval。
(3)關於ast.literal_eval的解釋,詳情參見:http://docs.python.org/library/ast.html#ast.literal_eval
【後記 2011-12-20】
後來的經驗,證實上述結論,是不許確的。
實際狀況是,在用ast.literal_eval的時候,遇到不少字典形式的字符串,轉換爲字典的時候,結果都會出錯,可是用eval,倒是能夠正常解析的。
而對於null沒有定義的問題,不管是ast.literal_eval和eval,二者都不支持的,由於自己python不支持null,python中的變量「空」,不是null,也不是NULL,而是None。因此,一個解決辦法是,定義一個全局變量:
null = '' #由於此到處理的是字符,因此此處定義爲空字符串
而後在函數裏面,加上
global null
而後再去調用eval,就能夠正常使用了。
實際證實,至少此處我遇到的,eval處理不少字典類字符串轉換爲字典變量的時候,仍是很好用的。
【結論 2011-12-20】
1.將字典形式字符串轉換爲字典變量的時候,eval比ast.literal_eval更好用。
2.eval和ast.literal_eval,都不支持null。能夠經過,在全局定義一個 null='',在函數內加上global null,以解決此問題。
轉自:http://againinput4.blog.163.com/blog/static/172799491201111143108624/?suggestedreading&wumii