รักษากรณีใน ConfigParser หรือไม่


92

ฉันได้พยายามใช้โมดูลConfigParserของ Python เพื่อบันทึกการตั้งค่า สำหรับแอปของฉันสิ่งสำคัญคือฉันต้องรักษากรณีของแต่ละชื่อในส่วนของฉัน เอกสารระบุว่าการส่ง str () ไปยังConfigParser.optionxform ()จะทำได้สำเร็จ แต่มันไม่ได้ผลสำหรับฉัน ชื่อเป็นตัวพิมพ์เล็กทั้งหมด ฉันพลาดอะไรไปรึเปล่า?

<~/.myrc contents>
[rules]
Monkey = foo
Ferret = baz

Python pseudocode ของสิ่งที่ฉันได้รับ:

import ConfigParser,os

def get_config():
   config = ConfigParser.ConfigParser()
   config.optionxform(str())
    try:
        config.read(os.path.expanduser('~/.myrc'))
        return config
    except Exception, e:
        log.error(e)

c = get_config()  
print c.options('rules')
[('monkey', 'foo'), ('ferret', 'baz')]

คำตอบ:


116

เอกสารมีความสับสน สิ่งที่พวกเขาหมายถึงคือ:

import ConfigParser, os
def get_config():
    config = ConfigParser.ConfigParser()
    config.optionxform=str
    try:
        config.read(os.path.expanduser('~/.myrc'))
        return config
    except Exception, e:
        log.error(e)

c = get_config()  
print c.options('rules')

คือแทนที่ optionxform แทนที่จะเรียกมันว่า; การลบล้างสามารถทำได้ในคลาสย่อยหรือในอินสแตนซ์ เมื่อลบล้างให้ตั้งค่าเป็นฟังก์ชัน (แทนที่จะเป็นผลลัพธ์ของการเรียกใช้ฟังก์ชัน)

ตอนนี้ฉันได้รายงานว่านี่เป็นข้อบกพร่องและได้รับการแก้ไขแล้ว


ขอขอบคุณ. ใช้งานได้และฉันยอมรับว่าเอกสารมีความสับสน
pojo

39

สำหรับฉันได้ตั้งค่า optionxform ทันทีหลังจากสร้างวัตถุ

config = ConfigParser.RawConfigParser()
config.optionxform = str 

2
ใช้งานได้ดี! (โปรดทราบว่าใน python 3 เป็นชื่อคลาส "configparser" (ไม่มีตัวพิมพ์ใหญ่)
Noam Manos

1
@NoamManos: คุณกำลังอ้างถึงชื่อโมดูล (ชื่อคลาสยังคงเป็นConfigParser )
Jonas Byström

2
โปรดทราบว่ามันใช้ได้กับConfigParser.ConfigParser()
Jean-Francois T.

แน่นอน. มันได้ผล. ดีที่จะพูดถึงว่าพารามิเตอร์นี้ไม่ได้เชื่อมโยงกับ RawConfigParser () เป็นหลักเนื่องจากมันรองรับเช่นเดียวกับคลาส ConfigParser () ขอบคุณคน
ivanleoncz

7

เพิ่มในรหัสของคุณ:

config.optionxform = lambda option: option  # preserve case for letters

1
สิ่งนี้ดูเหมือนจะได้ผลสำหรับฉันอย่างน้อยใน python 2.7 และสะอาดกว่าคำตอบที่ยอมรับมาก ขอบคุณ foo!
hrbdg

2
นี่เหมือนกับคำตอบที่ได้คะแนนสูงสุด - ดูบรรทัดconfig.optionxform=str:) แทนที่จะเป็น lamdba ของคุณ @Martin v. Löwisใช้strฟังก์ชันฝังตัว
xuthus

@xuthus - อันที่จริงคุณสามารถใช้รหัส 11 บรรทัดแทน 1 บรรทัด ตามที่คุณต้องการ.
FooBar167

4

ฉันรู้ว่าคำถามนี้มีคำตอบ แต่ฉันคิดว่าบางคนอาจคิดว่าวิธีนี้มีประโยชน์ นี่คือคลาสที่สามารถแทนที่คลาส ConfigParser ที่มีอยู่ได้อย่างง่ายดาย

แก้ไขเพื่อรวมข้อเสนอแนะของ @ OozeMeister:

class CaseConfigParser(ConfigParser):
    def optionxform(self, optionstr):
        return optionstr

การใช้งานจะเหมือนกับ ConfigParser ปกติ

parser = CaseConfigParser()
parser.read(something)

ดังนั้นคุณจึงไม่ต้องตั้งค่า optionxform ทุกครั้งที่สร้างใหม่ConfigParserซึ่งเป็นเรื่องที่น่าเบื่อ


เนื่องจากoptionxformเป็นเพียงวิธีการในRawConfigParserกรณีที่คุณจะไปไกลถึงการสร้างคลาสย่อยของคุณเองคุณควรแทนที่วิธีการในคลาสย่อยแทนที่จะกำหนดใหม่ในแต่ละอินสแตนซ์:class CaseConfigParser(ConfigParser): def optionxform(self, optionstr): return optionstr
OozeMeister

@OozeMeister ความคิดที่ดี!
icedtrees

2

ข้อแม้:

หากคุณใช้ค่าเริ่มต้นกับ ConfigParser เช่น:

config = ConfigParser.SafeConfigParser({'FOO_BAZ': 'bar'})

จากนั้นลองทำให้ตัวแยกวิเคราะห์คำนึงถึงขนาดตัวพิมพ์โดยใช้สิ่งนี้:

config.optionxform = str

ตัวเลือกทั้งหมดของคุณจากไฟล์FOO_BAZกำหนดค่าจะคงตัวพิมพ์ไว้แต่จะถูกแปลงเป็นตัวพิมพ์เล็ก

หากต้องการให้ค่าเริ่มต้นใช้กรณีของพวกเขาให้ใช้คลาสย่อยเช่นในคำตอบ @icedtrees:

class CaseConfigParser(ConfigParser.SafeConfigParser):
    def optionxform(self, optionstr):
        return optionstr

config = CaseConfigParser({'FOO_BAZ': 'bar'})

ตอนนี้FOO_BAZจะทำให้กรณีที่มันและคุณจะไม่ต้องInterpolationMissingOptionError

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.