2010-02-03 36 views
11

Tôi đang sử dụng ConfigParser để tải dữ liệu từ một tập tin cấu hình như sau:Làm thế nào để loại trừ DEFAULTs khỏi Python ConfigParser .items()?

test.conf:

[myfiles] 
fileone: %(datadir)s/somefile.foo 
filetwo: %(datadir)s/nudderfile.foo 

load.py:

import ConfigParser 

config = ConfigParser.ConfigParser({'datadir': '/tmp'}) 
config.read('test.conf') 

print config.items('myfiles') 
print config.get('myfiles', 'datadir') 

Output :

$ python load.py 
[('datadir', '/tmp'), ('filetwo', '/tmp/nudderfile.foo'), ('fileone', '/tmp/somefile.foo')] 
/tmp 

Tôi rất ngạc nhiên khi mặc định thay thế biến ('datadir', '/tmp') hiển thị như một phần của. items().get() trả về, như thể chúng là các giá trị trong tệp cấu hình. Hành vi này có được mong đợi không? Bất kỳ công việc nào xung quanh, để tôi chỉ có thể lặp lại .items() mà không nhận được các giá trị từ điển mặc định trong đó, nhưng vẫn sử dụng phép nội suy ma thuật?

Tham chiếu: http://docs.python.org/library/configparser.html

Cảm ơn!

Cập nhật: Đã được chỉ ra rằng đây là hành vi mong đợi: mặc định giống như bất kỳ cặp tên/giá trị nào khác trong tệp cấu hình. Tương tự như vậy, các cặp tên/giá trị trong file cấu hình cũng có sẵn để "suy ma thuật", vì vậy nếu tôi xác định:

foo: bar 
zap: %(foo)snowl 

tôi sẽ nhận được [... ('zap': 'barnowl')]

Đó là khá gọn gàng, nhưng tôi vẫn tự hỏi nếu tôi có thể thực hiện những gì tôi muốn thực hiện: lặp qua các cặp tên/giá trị trong các tệp cấu hình của tôi, với nội suy của các biến, không có các giá trị mặc định.

Kịch bản cụ thể của tôi là: Tôi muốn khởi tạo đối tượng cấu hình với một cái gì đó như {basedir: '/foo/bar'}, vì đường dẫn tuyệt đối đến các tệp nhất định khác nhau tùy theo cài đặt. Sau đó, tôi cần truyền đối tượng cấu hình đó xung quanh và có nhiều lớp khác lặp lại thông qua các tệp. Tôi không muốn mọi lớp đọc cấu hình phải biết rằng nó đã được khởi tạo với các giá trị mặc định và nó sẽ bỏ qua chúng vì chúng không phải là các tệp thực sự. Điều này có thể không? Bất kỳ cách nào để ẩn các giá trị mặc định từ .item() và .get() nhưng vẫn có nội suy? Cảm ơn!

+2

Tôi không thể hiểu được tại sao đây là hành vi mặc định, chứ chưa nói lý do tại sao không có cách nào để tắt nó đi. –

Trả lời

1

Hãy thử điều này:

config = ConfigParser.ConfigParser({'blahblahblah': 'blah'}) 
config.read('test.conf') 

Mấu chốt blahblahblah cũng sẽ xuất hiện trong items, không phải vì đó là một mẫu trong file .ini, nhưng vì bạn chỉ định nó như là một mặc định. Đây là cách ConfigParser xử lý mặc định: nếu nó không thể tìm thấy chúng trong tệp, nó gán giá trị mặc định của chúng.

Vì vậy, có vẻ như với tôi bạn có một sự nhầm lẫn đơn giản về các khái niệm ở đây.

+0

Cảm ơn bạn đã làm rõ. Vì vậy, từ điển mặc định được sử dụng * cả * để cung cấp các giá trị mặc định cho các khóa nhất định và cho "phép nội suy ma thuật" của các biến được nhúng trong tệp cấu hình. Thêm vào đó, các biến được định nghĩa trong tập tin cấu hình cũng được sử dụng cho "suy ma thuật", vì vậy nếu tôi xác định: foo: thanh zap:% (foo) snowl tôi sẽ nhận được [... ('zap ':' barnowl ')] Điều đó khá gọn gàng, nhưng tôi vẫn tự hỏi liệu tôi có thể thực hiện những gì tôi muốn thực hiện hay không: lặp qua cặp tên/giá trị trong tệp cấu hình của tôi, với nội suy của các biến, không có giá trị mặc định. – user264902

4

Nói chung, tôi đã tìm thấy lớp học configparser.Configparser rất hữu ích, nhưng cũng thiếu. Others have, too.

Tuy nhiên, nó thể được subclassed và kéo dài, đôi khi độc đáo, đôi khi không quá độc đáo (= rất thực hiện phụ thuộc)

Dưới đây là một giải pháp cho vấn đề của bạn, thử nghiệm trong Python3:

class ConfigParser(configparser.ConfigParser): 
    """Can get options() without defaults 
    """ 
    def options(self, section, no_defaults=False, **kwargs): 
     if no_defaults: 
      try: 
       return list(self._sections[section].keys()) 
      except KeyError: 
       raise NoSectionError(section) 
     else: 
      return super().options(section, **kwargs) 

Đây là một trong những ví dụ xấu, bởi vì nó là một phần sao chép the source code của options(). Sẽ thú vị hơn nếu lớp cơ sở configparser RawConfigParser sẽ cung cấp bộ thu thập nội bộ của các tùy chọn _options(self, section) sẽ kết hợp với dàn diễn viên ngoại lệ và options() sẽ sử dụng điều đó. Sau đó, trong phân lớp chúng tôi có thể sử dụng lại số _options().

Đối với Python 2, tôi tin rằng thay đổi duy nhất là cuộc gọi super() đến super(ConfigParser,self).

Sau đó bạn có thể sử dụng:

print config.options('myfiles', no_defaults=True) 

Và cũng sử dụng danh sách đó để lặp.

+0

Bạn đang đi đúng hướng, tuy nhiên anh ta hỏi về .items(), chứ không phải .options(). Tôi nghĩ điều này sẽ đưa anh ta đến đó. –

+0

Tôi hiểu câu hỏi của ông là làm thế nào để "lặp lại các cặp tên/giá trị trong các tệp cấu hình của tôi, với nội suy của các biến, không có các giá trị mặc định." Và đó là những gì các mã trên không. Với tôi đó là câu trả lời chính xác. Thật không may, như thường lệ, áp phích của câu hỏi dường như không hoạt động. Nếu không, chúng tôi có thể cho anh ta quyết định xem đó có thể chấp nhận câu trả lời hay không. – cfi

+0

Vâng, câu hỏi chạy liên tục và cần tập trung. Anh ta sử dụng .items trong mã, và trong câu cuối cùng. Anh ta yêu cầu tên/cặp val, đó là những gì. Tùy chọn chỉ trả về các phím. Câu trả lời của bạn đã giúp tôi ghi đè lên. –

2

Bạn không thể lọc ra các giá trị mặc định?

ví dụ .:

filtered_items = [x for x in config.items('myfiles') if x[0] not in config.defaults()]

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