बिना सेक्शन नाम की फाइल को पढ़ने के लिए कॉन्फिगरेशन का उपयोग करना


87

मैं ConfigParserएक स्क्रिप्ट के रनटाइम कॉन्फ़िगरेशन को पढ़ने के लिए उपयोग कर रहा हूं ।

मैं एक अनुभाग नाम प्रदान नहीं करने का लचीलापन रखना चाहूंगा (ऐसी स्क्रिप्ट हैं जो काफी सरल हैं; उन्हें 'अनुभाग' की आवश्यकता नहीं है)। ConfigParserएक NoSectionErrorअपवाद फेंक देंगे , और फ़ाइल को स्वीकार नहीं करेंगे।

मैं कैसे कर सकता हूँ configParser बस (key, value)अनुभाग नाम के बिना एक विन्यास फाइल के tuples पुनः प्राप्त ?

उदाहरण के लिए:

key1=val1
key2:val2

मैं कॉन्फिग फाइल पर नहीं लिखूंगा।


जवाबों:


52

एलेक्स मार्टेली नेConfigParser पार्स .propertiesफ़ाइलों का उपयोग करने के लिए एक समाधान प्रदान किया (जो कि स्पष्ट रूप से अनुभाग-कम विन्यास फाइल हैं)।

उनका समाधान एक फाइल-जैसा रैपर है जो स्वचालित रूप से डमी सेक्शन को शीर्षक देकर ConfigParserआवश्यकताओं को पूरा करेगा।


+1 क्योंकि वह वही है जो मैं सुझाने वाला था। जब आपको करना है तो सभी जटिलता को जोड़ दें, बस एक अनुभाग जोड़ें!
देशभक्ति

5
@ जथनवाद: ऐसे मामले हैं जहाँ आप मौजूदा कॉन्फिग / प्रॉपर्टीज़ फ़ाइलों के साथ काम करना चाहते हैं, जिन्हें मौजूदा जावा कोड द्वारा पढ़ा जाता है और आप उन हेडर को संशोधित करने का जोखिम नहीं जानते हैं
tshepang

43

द्वारा प्रबुद्ध jterrace द्वारा इस जवाब , मैं इस समाधान के साथ आते हैं:

  1. एक स्ट्रिंग में पूरी फाइल पढ़ें
  2. डिफ़ॉल्ट अनुभाग नाम के साथ उपसर्ग
  3. किसी फ़ाइल जैसी ऑब्जेक्ट की नकल करने के लिए स्ट्रिंगो का उपयोग करें
ini_str = '[root]\n' + open(ini_path, 'r').read()
ini_fp = StringIO.StringIO(ini_str)
config = ConfigParser.RawConfigParser()
config.readfp(ini_fp)


संपादित भविष्य Googler के लिए: अजगर 3.4+ के रूप में readfpहटा दिया गया है, और StringIOअब कोई आवश्यकता नहीं है। इसके बजाय हम read_stringसीधे उपयोग कर सकते हैं :

with open('config_file') as f:
    file_content = '[dummy_section]\n' + f.read()

config_parser = ConfigParser.RawConfigParser()
config_parser.read_string(file_content)

यह भी एक साधारण मेकफाइल (केवल उपनाम के साथ) पार्स करने के लिए अद्भुत काम करता है! इस उत्तर से प्रेरित होकर, पायथन में अपने पूर्ण आदेशों से उपनामों को प्रतिस्थापित करने के लिए एक पूरी स्क्रिप्ट है
गाबोरस

41

आप इसे कोड की एक पंक्ति में कर सकते हैं।

अजगर 3 में, अपने कॉन्फिग फाइल डेटा में एक फर्जी सेक्शन हेडर को प्रीपेन्ड करें और इसे पास करें read_string()

from configparser import ConfigParser

parser = ConfigParser()
with open("foo.conf") as stream:
    parser.read_string("[top]\n" + stream.read())  # This line does the trick.

आप itertools.chain()किसी अनुभाग हेडर के लिए अनुकरण करने के लिए भी उपयोग कर सकते हैं read_file()। यह उपरोक्त दृष्टिकोण की तुलना में अधिक मेमोरी-कुशल हो सकता है, जो कि अगर आपको एक बाधा रनटाइम वातावरण में बड़ी कॉन्फिग फाइल करने में मददगार हो सकता है।

from configparser import ConfigParser
from itertools import chain

parser = ConfigParser()
with open("foo.conf") as lines:
    lines = chain(("[top]",), lines)  # This line does the trick.
    parser.read_file(lines)

अजगर 2 में, अपने कॉन्फिग फ़ाइल डेटा में एक फर्जी सेक्शन हेडर प्रीपेन्ड करें, एक StringIOऑब्जेक्ट में रिजल्ट को रैप करें और इसे पास करें readfp()

from ConfigParser import ConfigParser
from StringIO import StringIO

parser = ConfigParser()
with open("foo.conf") as stream:
    stream = StringIO("[top]\n" + stream.read())  # This line does the trick.
    parser.readfp(stream)

इनमें से किसी भी एप्रोच के साथ, आपकी कॉन्फिगरेशन सेटिंग उपलब्ध होगी parser.items('top')

आप स्ट्रिंग 3 का उपयोग अजगर 3 में भी कर सकते हैं, शायद पुराने और नए दोनों अजगर व्याख्याकारों के साथ संगतता के लिए, लेकिन ध्यान दें कि यह अब ioपैकेज में रहता है और readfp()अब पदावनत हो गया है।

वैकल्पिक रूप से, आप विन्यासकर्ता के बजाय TOML पार्सर का उपयोग करने पर विचार कर सकते हैं ।


18

आप ऐसा करने के लिए बस ConfigObj लाइब्रेरी का उपयोग कर सकते हैं: http://www.voidspace.org.uk/python/configobj.html

अपडेट किया गया: यहां नवीनतम कोड खोजें ।

यदि आप डेबियन / उबंटू के अधीन हैं, तो आप अपने पैकेज मैनेजर का उपयोग करके इस मॉड्यूल को स्थापित कर सकते हैं:

apt-get install python-configobj

उपयोग का एक उदाहरण:

from configobj import ConfigObj

config = ConfigObj('myConfigFile.ini')
config.get('key1') # You will get val1
config.get('key2') # You will get val2

8

ऐसा करने का सबसे आसान तरीका मेरी राय में, अजगर के सीएसवी पार्सर का उपयोग करना है। इस दृष्टिकोण के साथ-साथ परीक्षण ड्राइवर के प्रदर्शन को पढ़ने / लिखने का कार्य यहां दिया गया है। यह काम करना चाहिए बशर्ते कि मूल्यों को बहु-पंक्ति होने की अनुमति न हो। :)

import csv
import operator

def read_properties(filename):
    """ Reads a given properties file with each line of the format key=value.  Returns a dictionary containing the pairs.

    Keyword arguments:
        filename -- the name of the file to be read
    """
    result={ }
    with open(filename, "rb") as csvfile:
        reader = csv.reader(csvfile, delimiter='=', escapechar='\\', quoting=csv.QUOTE_NONE)
        for row in reader:
            if len(row) != 2:
                raise csv.Error("Too many fields on row with contents: "+str(row))
            result[row[0]] = row[1] 
    return result

def write_properties(filename,dictionary):
    """ Writes the provided dictionary in key-sorted order to a properties file with each line of the format key=value

    Keyword arguments:
        filename -- the name of the file to be written
        dictionary -- a dictionary containing the key/value pairs.
    """
    with open(filename, "wb") as csvfile:
        writer = csv.writer(csvfile, delimiter='=', escapechar='\\', quoting=csv.QUOTE_NONE)
        for key, value in sorted(dictionary.items(), key=operator.itemgetter(0)):
                writer.writerow([ key, value])

def main():
    data={
        "Hello": "5+5=10",
        "World": "Snausage",
        "Awesome": "Possum"
    }

    filename="test.properties"
    write_properties(filename,data)
    newdata=read_properties(filename)

    print "Read in: "
    print newdata
    print

    contents=""
    with open(filename, 'rb') as propfile:
        contents=propfile.read()
    print "File contents:"
    print contents

    print ["Failure!", "Success!"][data == newdata]
    return

if __name__ == '__main__': 
     main() 

csvसामान्य ConfigParserशिकायत को हल करने के लिए मॉड्यूल का +1 चालाक उपयोग । आसानी से और अधिक सामान्यीकृत और दोनों पायथन 2 और 3 संगत किया
मार्टीन्यू

6

खुद इस समस्या में भाग जाने के बाद, मैंने कॉन्फिगरेशन (Python 2 में संस्करण) के लिए एक पूर्ण रैपर लिखा, जो एलेक्स मार्सेली के स्वीकृत उत्तर पर जुड़े दृष्टिकोण के आधार पर पारदर्शी रूप से बिना सेक्शन के फाइलों को पढ़ और लिख सकता है। यह विन्यासकर्ता के किसी भी उपयोग के लिए एक ड्रॉप-इन प्रतिस्थापन होना चाहिए। यदि किसी को उस पेज की जरूरत हो तो उसे पोस्ट करना।

import ConfigParser
import StringIO

class SectionlessConfigParser(ConfigParser.RawConfigParser):
    """
    Extends ConfigParser to allow files without sections.

    This is done by wrapping read files and prepending them with a placeholder
    section, which defaults to '__config__'
    """

    def __init__(self, *args, **kwargs):
        default_section = kwargs.pop('default_section', None)
        ConfigParser.RawConfigParser.__init__(self, *args, **kwargs)

        self._default_section = None
        self.set_default_section(default_section or '__config__')

    def get_default_section(self):
        return self._default_section

    def set_default_section(self, section):
        self.add_section(section)

        # move all values from the previous default section to the new one
        try:
            default_section_items = self.items(self._default_section)
            self.remove_section(self._default_section)
        except ConfigParser.NoSectionError:
            pass
        else:
            for (key, value) in default_section_items:
                self.set(section, key, value)

        self._default_section = section

    def read(self, filenames):
        if isinstance(filenames, basestring):
            filenames = [filenames]

        read_ok = []
        for filename in filenames:
            try:
                with open(filename) as fp:
                    self.readfp(fp)
            except IOError:
                continue
            else:
                read_ok.append(filename)

        return read_ok

    def readfp(self, fp, *args, **kwargs):
        stream = StringIO()

        try:
            stream.name = fp.name
        except AttributeError:
            pass

        stream.write('[' + self._default_section + ']\n')
        stream.write(fp.read())
        stream.seek(0, 0)

        return ConfigParser.RawConfigParser.readfp(self, stream, *args,
                                                   **kwargs)

    def write(self, fp):
        # Write the items from the default section manually and then remove them
        # from the data. They'll be re-added later.
        try:
            default_section_items = self.items(self._default_section)
            self.remove_section(self._default_section)

            for (key, value) in default_section_items:
                fp.write("{0} = {1}\n".format(key, value))

            fp.write("\n")
        except ConfigParser.NoSectionError:
            pass

        ConfigParser.RawConfigParser.write(self, fp)

        self.add_section(self._default_section)
        for (key, value) in default_section_items:
            self.set(self._default_section, key, value)

5

Blueicefield के उत्तर ने configobj का उल्लेख किया है, लेकिन मूल काम केवल पायथन 2 का समर्थन करता है। इसमें अब Python 3+ संगत उपकरण है:

https://github.com/DiffSK/configobj

API परिवर्तित नहीं हुए हैं, यह देखें कि यह डॉक्टर है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.