2010-02-11 20 views
10

Tôi viết một bộ kiểm tra DB nhỏ, mà đọc file cấu hình với các truy vấn và dự kiến ​​kết quả, ví dụ .:Python: Đọc tập tin cấu hình với nhiều dòng cho mỗi khoá

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';" 

này hoạt động tốt; Tôi chia mỗi dòng bằng cách sử dụng string.partition('=') của Python.

Vấn đề của tôi là các truy vấn SQL rất dài. Hiện tại, tôi chỉ dán các truy vấn này dưới dạng một lớp lót, điều này rất xấu và không thể duy trì được.

Tôi muốn tìm một cách thanh lịch, Pythonic để đọc bên phải của một biểu thức, ngay cả khi trải dài trên nhiều dòng.

Ghi chú:

  • truy vấn SQL của tôi có thể chứa các =
  • Tôi không ưa thích các ý tưởng về buộc " s xung quanh phía bên tay phải, bởi vì có rất nhiều tác phẩm hiện có mà không có nó.

EDIT:

ConfigParser là rất tốt, nhưng nó buộc tôi để thêm khoảng trắng hoặc tab ở đầu mỗi dòng trong một entry có nhiều dòng. Đây có thể là một nỗi đau lớn.

Cảm ơn trước,

Adam

+0

không gian này/tab không được bao gồm trong giá trị cuối cùng – SilentGhost

+0

bạn có thể xây dựng? Không hiểu nhận xét của bạn. –

Trả lời

9

Đây là gần như chính xác việc sử dụng hợp cụ thể mà làm cho chúng tôi chuyển sang YAML (Wikipedia, python implementation, documentation; bạn có thể muốn nhìn vào JSON như một sự thay thế).YAML có một số lợi thế hơn configparser hoặc json:

  • khả năng đọc của con người (tốt hơn JSON cho tệp lớn hơn);
  • có thể tuần tự hóa các đối tượng python tùy ý (làm cho nó không an toàn như pickle, nhưng có chức năng safe_load trong triển khai python để giảm bớt vấn đề này). Điều này đã hữu ích cho một cái gì đó đơn giản như một đối tượng datetime.

Đối với đầy đủ sake, những nhược điểm chính (IMO):

  • Python thực hiện bởi một bậc chậm hơn so với thực hiện JSON;
  • ít di động trên các nền tảng hơn JSON.

Ví dụ

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']) 

in

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

+1: yaml rất tốt cho cấu hình như vậy – van

+0

+1 Ý tưởng tuyệt vời. Sẽ nhìn vào nó. –

+0

+1 phù hợp với trường hợp sử dụng đẹp mắt. –

12

Các Python thư viện chuẩn mô-đun ConfigParser hỗ trợ này theo mặc định. Các tập tin cấu hình có được trong một định dạng chuẩn:

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

tập tin cấu hình trên có thể được đọc với đoạn mã sau:

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

Tôi gặp vấn đề với giải pháp này do lỗi được đưa ra khi phân tích cú pháp tệp. Theo tài liệu, cần phải thụt lề các giá trị đa dòng. Tôi đã thêm 4 dấu cách khi bắt đầu "ở dòng tiếp theo" và nó hoạt động. – MikeCPT

1

tôi bạn sẽ đề nghị sử dụng một biểu thức chính quy ... Các mã có thể trông như thế này để cung cấp cho bạn bắt đầu:

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) 

Kết quả của ví dụ này là:

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

Hy vọng điều đó sẽ hữu ích!

Kính trọng, Christoph

+1

+1 Điều đó sẽ hiệu quả, nhưng tôi thực sự thích một gói sẵn sàng hỗ trợ tất cả các loại điều kiện cạnh. –

Các vấn đề liên quan