如何开发然后解析数据结构

时间:2010-10-13 04:02:38

标签: python parsing file-io data-structures

我正在设计一个天气程序,我需要跟踪某些事情并允许用户添加将被保存并随后稍后阅读的数据。我的领域是

市 州 压缩 每小时一次

我可能有更多我想稍后使用此配置文件,所以我希望它有这样的东西:

[LOCATIONS]
Phoenix:AZ:85001:KPHX
Dallas:TX:75201:KDFW

[USER CONFIGS]
for later

设置写入文件应该不是很难,只需创建要写入的文件对象,写入[Locations]后跟我计划在列表中保存的数据,然后用冒号连接列表

然而,我对如何阅读它感到有点困惑。

我知道我可以一次读取一行并检查行=='[LOCATIONS]',然后读取行,直到我变成一个空行,但是如果有一个额外的空白怎么办?线。或者我应该使用startwith('[')并且不添加空行。

尝试在网上做一些谷歌搜索,因为对于新的程序员来说这似乎是一个相当常见的问题,但我已经空了(除了一些了解CVS模块,我认为这不能帮助我)

使用sqlite的正式数据库会有点过分。每个用户最多可能有20-50个条目,大多数会更少。

同样在程序中,GUI中输入的每个数据项(状态除外)都可以导致所有其他数据都使用正确的值进行更新。由于几乎每个数据项都可以作为主角,我不确定如何设置它以便于搜索。我应该为City制作一个包含{'Dallas':('TX','75201','KDFW')}等结构的字典来帮助查找Metars {'KDFW':('Dallas',' TX','75201')}和Zips {'75201':('DALLAS','TX','KDFW')}?这看起来好于迭代每一行以检查匹配,但考虑到原始结构将是['Dallas','TX','75201','KDFW']等列表,这似乎有点浪费。什么会很好,因为类似字典的对象可以让每个项目都像一个键,返回关联中的其他值。

赞赏各种想法和想法。

5 个答案:

答案 0 :(得分:2)

要存储数据,您可以使用XML。然后使用python附带的任何XML解析器,SAX或DOM来读取它。

由于数据的大小非常小(每个用户只有大约20-25个条目),因此您可以采用首先了解搜索项的方法,无论是州名还是其密码等。(要求用户在GUI中输入。

假设数据存储为[City State Pin Mater],您可以在相应的列中搜索。例如,如果用户输入12345,并且您知道它是一个引脚,您只需要搜索列表数据的第三个索引,然后返回列表。对于州名,您将在第二列中搜索。

这种方法即使记录数量很大,也就是几百个。

答案 1 :(得分:1)

如果你提出了语法,你有一个ConfigParser module因此你可以轻松地解析文件,获得按部分或任何你想要的方式分组的所有字符串。但后来它会导致其他麻烦 - 只要考虑对文件的大量更新。

所以我建议也使用sqlite。它是一个标准模块,它很小,所以没有开销或额外的依赖。

答案 2 :(得分:0)

您可以使用sqlite或任何其他类型的数据库(如Mysql等)来存储数据。

答案 3 :(得分:0)

我不建议像你发布的那样使用ini格式的文件。

我认为你有两个一般选择:  *使用数据库,如@ ghostdog74建议的sqlite  *使用通用,易于分析的数据结构使用平面文件

对于平面文件,XML或JSON可能是最好的选择。现在大多数语言都有内置的解析器。 JSON更高效,但XML更具可读性和结构性。

当然,这样做的缺点是你基本上必须解析/读取整个文件才能进行查找。好处是它应该是一个微不足道的代码。

您正在谈论有效地创建自己的索引,因此您可以通过ZIP或metar等轻松查找。我建议这是不必要的。如果你真的想要,你可以在内存中使用哈希表来存储对象的引用,但除非你一次读取文件然后进行多次查找,否则构建哈希表的开销可能不仅仅是循环找到你需要的东西。我得到的印象是这是一个Web应用程序,您可以在其中阅读文件,执行一次或两次查找,并吐出一个网页。

如果您的数据处于循环遍历所有记录的行为导致明显的性能影响,那么您将进入应该使用真实数据库的领域,例如sqlite,mysql,postgresql等任何更少的东西,你只需要以一种不那么好的方式重新发明他们已经完成的索引和文件存储。

答案 4 :(得分:0)

就数据结构而言,我自学了如何使用xml.dom。事实证明,我真的很喜欢它。我现在看到为什么程序员更多地使用它来配置文件等。

我决定开发自己的类,它有点像字典,但可以有多个键。与字典不同,它可以有多个具有相同值的键(但我设计的key()方法将只返回唯一值)。

以下是代码:

#! /usr/bin/python2.6
# -*- coding: utf-8 -*-
'''makes a new dictionary-type class

This class allows for multiple keys unlike the dictionary type.
The keys are past first as a list or tuple. Then, the data is to 
be passed in a tuple or list of tuples or lists with the exact 
number of data items per list/tuple.

Example:

    >>> from superdict import SuperDict
    >>> keynames = ['fname', 'lname', 'street', 'city', 'state', 'zip']
    >>> names = [
    ...     ['Jim', 'Smith', '123 Cherry St', 'Topeka', 'KS', '73135'],
    ...     ['Rachel', 'West', '456 Bossom Rd', 'St Louis', 'MO', '62482']
    ...     ]
    >>> dictionary = SuperDict(keynames, names)

There is a SuperDict.keys method that shows all the keys for a given keyname
to be accessed as in:

    >>> print dictionary.keys('city')
    ['Topeka', 'St Louis']

The add method is used to pass a list/tuple but must have the same number of
'fields'.
    >>> dictionary.add(['John', 'Richards', '6 Tulip Ln', 'New Orleans', 'LA', '69231'])

The extend method is used to pass a multiple lists/tuples inside a list/tuple as above.

    >>> new_names = [
    ['Randy', 'Young', '54 Palm Tree Cr', 'Honolulu', 'HA', '98352'],
    ['Scott', 'People', '31932 5th Ave', 'New York', 'NY', '03152']
    ]
    >>> dictonary.extend(new_names)

The data attribute can be used to access the raw data as in:
    >>> dictionary.data
    [['Jim', 'Smith', '123 Cherry St', 'Topeka', 'KS', '73135'], ['Rachel', 'West', '456 Bossom Rd', 'St Louis', 'MO', '62482'], ['Randy', 'Young', '54 Palm Tree Cr', 'Honolulu', 'HA', '98352'], ['Scott', 'People', '31932 5th Ave', 'New York', 'NY', '03152']]

The data item is retrieved with the find method as below:

    >>> dictionary.find('city', 'Topeka')
    ['Jim', 'Smith', '123 Cherry St', 'Topeka', 'KS', '73135']

What if there are more than one? Use the extended options of find to
find a second field as in:

    >>> dictionary.find('city', 'Topeka', 'state', 'KS')
    ['Jim', 'Smith', '123 Cherry St', 'Topeka', 'KS', '73135']

To find all the fields that match, use findall (second keyname 
is available for this just as in the find method):

    >>> dictionary.find('city', 'Topeka')
    [['Jim', 'Smith', '123 Cherry St', 'Topeka', 'KS', '73135'], ['Ralph', 'Johnson', '513 Willow Way', 'Topeka', 'KS', '73189']]


The delete method allows one to remove data, if needed:
    >>> dictionary.delete(new_names[0])
    >>> dictionary.data
    [['Jim', 'Smith', '123 Cherry St', 'Topeka', 'KS', '73135'], ['Rachel', 'West', '456 Bossom Rd', 'St Louis', 'MO', '62482'], ['Scott', 'People', '31932 5th Ave', 'New York', 'NY', '03152']]

maintainer: <signupnarnie@gmail.com>

LICENSE: GPL version 2
Copywrite 2010
'''

__version__ = 0.4

indexnames = ['city','state','zip','metar']
datasample = [
    ['Pawhuska', 'OK', '74056', 'KBVO'],
    ['Temple', 'TX', '76504', 'KTPL']
    ]


class SuperDict(object):
    '''
    superdict = SuperDict(keynames, data)

    Keynames are a list/tuple of the entry names
    Data is a list/tuple of lists/tuples containing the data1

    All should be of the same length

    See module doc string for more information
    '''

    def __init__(self, indexnames, data=None):
        self.keydict = dict()
        if data:
            self.data = data
        for index, name in enumerate(indexnames):
            self.keydict[name.lower()] = index

    def keys(self, index, sort=False):
        '''
        SuperDict.keys(keyname, sort=False)

        Returns all the "keys" for the keyname(field name) but duplicates
        are removed.

        If sort=True, then the keys are sorted
        '''
        index = index.lower()
        keynames = []
        for item in self.data:
            key = item[self.keydict[index]]
            if key:
                keynames.append(key)
        keynames = list(set(keynames))
        if sort:
            keynames = sorted(keynames)
        return keynames

    def add(self, data):
        '''
        SuperDict.add(list/tuple)

        adds another another entry into the dataset
        '''
        if self.data:
            if not len(data) == len(self.data[0]):
                print 'data length mismatch'
                return
        self.data.append(data)

    def extend(self, data):
        '''
        SuperDict([list1, list2])
        SuperDict((tuple1, tuple2))

        Extends the dataset by more than one field at a time
        '''
        for datum in data:
            self.add(datum)

    def delete(self, data):
        '''
        SuperDict.delete(list/tuple)

        Deletes an entry matching the list or tuple passed to the method
        '''
        # question for later: should I return true or false if something delete or not
        for index, item in enumerate(self.data):
            if data == item:
                del self.data[index]

    def find(self, keyname1, data1, keyname2=None, data2=None):
        '''
        SuperDict(keyname1, data1, keyname2=None, data2=None)

        Look for the first entry based on the value of a keyname(s).
        '''
        keyname1 = keyname1.lower()
        if keyname2:
            keyname2 = keyname2.lower()
        for item in self.data:
            if data1 == item[self.keydict[keyname1]]:
                if not data2:
                    return item
                elif data2 == item[self.keydict[keyname2]]:
                    return item

    def findall(self, keyname1, data1, keyname2=None, data2=None):
        '''
        SuperDict.findall(keyname1, data1, keyname2=None, data2=None)
        '''
        keyname1 = keyname1.lower()
        if keyname2:
            keyname2 = keyname2.lower()
        items = []
        for item in self.data1:
            if data1 == item[self.keydict[keyname1]]:
                if not data2:
                    items.append(item)
                elif data2 == item[self.keydict[keyname2]]:
                    items.append(item)
        return items