2010-02-11 22 views
10

我寫一個小DB測試套件,其內容與查詢配置文件和預期結果的多條線路的配置文件,例如:的Python:閱讀與每個鍵

query   = "SELECT * from cities WHERE name='Unknown';" 
count   = 0 
level   = 1 
name   = "Check for cities whose name should be null" 
suggested_fix = "UPDATE cities SET name=NULL WHERE name='Unknown';" 

這種運作良好;我使用Python的string.partition('=')劃分每行。

我的問題是很長的SQL查詢。目前,我只是將這些查詢粘貼爲單行,這是醜陋的,不可維護的。

我想找到一種優雅的Pythonic方式來閱讀表達式的權利,即使跨越多行。

注:

  • 我的SQL查詢可能包含=
  • 我不喜歡強迫周圍的右側" S的想法,因爲有許多現有文件,沒有它。

編輯:

ConfigParser是偉大的,但它迫使我在每行的開頭多行條目添加一個空格或製表符。這可能是一個很大的痛苦。

由於提前,

亞當

+0

這個空間/標籤不包含在最終的價值 – SilentGhost 2010-02-11 18:34:57

+0

你能否解釋一下?沒有理解你的評論。 – 2010-02-11 18:52:54

回答

9

這幾乎是完全用例,使我們切換到YAMLWikipediapython implementationdocumentation;你可能想在JSON看作爲替代)。YAML擁有configparserjson一些優勢:

  • 可讀性(比JSON更好地爲大文件);
  • 可以序列化任意python對象(這使得它與pickle一樣不安全,但在python實現中有一個safe_load函數來緩解這個問題)。這對於諸如datetime對象這樣簡單的事情已經很有用。

爲了完整起見,主要缺點(IMO):

  • Python實現由幅度比JSON執行慢的順序;
  • 跨平臺移植的可移植性低於JSON。

例如

import yaml 

sql = """ 
query   : "SELECT * from cities 
WHERE name='Unknown';" 
count   : 0 
level   : 1 
name   : "Check for cities whose name should be null" 
suggested_fix : "UPDATE cities SET name=NULL WHERE name='Unknown';" 
""" 

sql_dict = yaml.safe_load(sql) 

print(sql_dict['query']) 

打印

SELECT * from cities WHERE name='Unknown'; 
+0

+1:yaml非常適合這樣的配置 – van 2010-02-12 10:26:28

+0

+1好主意。將研究它。 – 2010-02-12 19:25:53

+0

+1非常適合用例。 – 2012-06-06 18:24:42

12

Python標準庫模塊ConfigParser默認支持這一點。配置文件必須是標準格式:

[Long Section] 
short: this is a normal line 
long: this value continues 
in the next line 

配置文件上面可以用下面的代碼讀取:

import ConfigParser 
config = ConfigParser.ConfigParser() 
config.read('longsections.cfg') 
long = config.get('Long Section', 'long') 
+1

由於在解析文件時出現錯誤,因此我遇到了此解決方案的問題。根據文檔,對於多行值,需要縮進。 我在「在下一行」開始處添加了4個空格,它起作用。 – MikeCPT 2017-09-02 08:22:46

1

我會建議使用正則表達式的...代碼可能看起來像這樣給你是開始:

import re 

test="""query = "select * from cities;" 
count = 0 
multine_query = "select * 
from cities 
    where name='unknown';" 
""" 

re_config = re.compile(r'^(\w+)\s*=\s*((?:".[^"]*")|(?:\d+))$', re.M) 
for key, value in re_config.findall(test): 
    if value.startswith('"'): 
     value = value[1:-1] 
    else: 
     value = int(value) 
    print key, '=', repr(value) 

這個例子的輸出是:

~> python test.py 
query = 'select * from cities;' 
count = 0 
multine_query = "select *\nfrom cities\n  where name='unknown';" 

希望有幫助!

問候, 克里斯托夫

+1

+1這應該可行,但我更喜歡現成的包,支持各種邊緣條件。 – 2010-02-12 09:44:52