簡體   English   中英

ConfigParser 慢嗎? ConfigParser 與丑陋的算法

[英]Is ConfigParser slow? ConfigParser vs. an ugly algorithm

我試圖改進我創建的 function 以將一堆 INI 文件解析為單個 JSON 文件。 當我寫這個 function 時我是一個新手,我不知道configparser模塊,所以現在我想利用它。

INPUT :INI 文件(父)包含對其他 INI 文件(子)的一長串引用。

目標:將 INI 父文件轉換為 JSON 並包含從所有子文件中獲取的一些信息。 換句話說:從一組 INI 文件中獲取一些信息並將它們導出到單個 JSON 文件中。

問題:我希望我的新代碼至少和舊代碼一樣快,但事實並非如此:它慢了 2 倍。 這是為什么? 是 ConfigParser 還是我? 性能真的很重要,我的 function 需要一秒鍾來解析大約 900 個 INI 文件,而舊的需要半秒鍾。

父示例

(它可以有數百行到數萬行):

[General]
Name = parent
...
   
[Item 000001]
Name = first item
path = "path/to/child_1.ini"
...

[Item 000002]
Name = second item
...

[...]

[Item 001000]
Name = thousandth item
...   

子示例

(它可以有少於 100 行到大約 200 行):

[General]
Name = name
ID = 12345
...

[Options]
...

JSON Output 示例

{
    "Parent": {
        "Name": "parent",
        "Count": "1000",
        [...]
        "child1": {
            "Name": "name",
            "ID": "12345",
            "Option1": "...",
            "Option2": "...",
            "Option3": "..." 
        },
        "child2": {
            "Name": "name2",
            "ID": "22222",
            "Option1": "...",
            "Option2": "...",
            "Option3": "..." 
        },
        [...]
        "child1000": {
            "Name": "name1000",
            "ID": "12332",
            "Option1": "...",
            "Option2": "...",
            "Option3": "..." 
        }
    }
}

舊代碼

def split_string_by_equal(string):
    str_operands = string.split(' = ')
    first_part = (str_operands[0]).strip()
    second_part = (' '.join(str_operands[1:])).strip()
    return [first_part, second_part]

def parse_ini_to_json(path):
    parent_dict = {}
    child_dict = {}
    num_child = 1
    parent_directory = os.path.dirname(testflow)
    with open(path, 'r') as parent_file:
        for line in tfl_file:
            left_part = split_string_by_equal(line)[0]
            right_part = split_string_by_equal(line)[1]
            if left_part in SOME_WORDS:
                parent_dict.update({left_part: do_something(parent_directory, right_part)})
            elif left_part == 'Count':
                parent_dict.update({'Count': right_part})
            elif left_part == 'JohnDoe':
                parent_dict['JohnDoe'] = right_part
            elif 'Item' in line:
                if child_dict:
                    parent_dict.update({'test{}'.format(num_child): child_dict})
                    child_dict = {}
                    num_child += 1
            elif left_part in SOME_OTHER_WORDS:
                child_dict.update({left_part: right_part})
            if left_part == 'path':
                child_dict.update(extract_data_from_child(right_part))
    if child_dict:
        parent_dict.update({'child{}'.format(num_test): child_dict})
    return parent_dict

def extract_data_from_child(path):
    """ same methodology used in above function """
    [...]
    return child_dict

新代碼

def get_config_parser(path):
    config = configparser.ConfigParser()
    config.optionxform = str
    config.read(path)
    return config

def parse_ini_to_json(path):
    config = get_config_parser(path)
    parent_directory = os.path.dirname(testflow)
    parent_dict = {}
    for key in config['Folders'].keys():
        parent_dict[key] = do_something( parent_directory, config['Folders'][key])
    parent_dict['Count'] = config['General']['Count']
    parent_dict['JohnDoe'] = config['General']['JohnDoe']
    counter = 1
    for key in config.keys():
        if 'Item' in key:
            child_dict = {}
            for child_prop in config[key].keys():
                if child_prop in SOME_WORDS:
                    child_dict[child_prop] = config[key][child_prop]
            child_path = config[key]['path']
            child_dict.update(extract_data_from_child(child_path))
            child_dict[f'child{counter}'] = child_dict
            counter += 1
    return parent_dict


def extract_data_from_child(path):
    config = sysfunc.get_config_parser(path)
    child_dict = {}
    for key in config['General'].keys():
        if key in SOME_KEYWORDS:
            child_dict[key] = config['General'][key]
    for key in config['Levels'].keys():
        if key in SOME_OTHER_KEYWORDS:
            child_dict[key] = config['Options'][key]
    try:
        some_value = config['Levels']['SomeKey']
    except KeyError:
        pass
    for key in config['Options'].keys():
        value = config['Options'][key]
        key_enabled = key.strip() + 'enabled'
        try:
            if config['Options'][key_enabled] == '0':
                continue
        except KeyError:
            continue
        if 'false' in value:
            value = '0'
        elif 'true' in value:
            value = '1'
        child_dict[key] = value
    return child_dict 

我希望我的新代碼至少和舊代碼一樣快,但事實並非如此:它慢了 2 倍。 這是為什么? 是 ConfigParser 還是我?

兩者都是。 要了解在您的代碼和 ConfigParser 中花費的時間,您應該考慮使用Profiler https://docs.python.org/3/library/profile.html是學習如何分析代碼的一個很好的起點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM