简体   繁体   中英

How can I store many variables in one file, and access those variables from a different file?

I want to create a 'mini-database'. I want to have one file with lots of variables, and be able to take those variables from the file, while also being able to add variables to the file? For example, lets suppose this is the 'mini-db':

hello = ['a', 'b', 'c']
world = ['d', 'e', 'f']
foo = ['g', 'h', 'i']

and from a different file, I would like to say something like:

print MiniDB.hello[0]

So basically access the variable. Also, I would need to write variables INTO the file. so something like this:

MiniDB.bar = ['j', 'k', 'l']

How can I do this?

shelve is the easiest way to do this. Mind the concurrency restrictions though.

This may not be what you are looking for, but this class allows storing program settings. You load it with default settings that represent the variables you need and embed dictionaries to generate namespaces. It is not perfect, but tries to allow multiple database definitions to coexist with each other while ensuring data types do not change. It has a limited field of usage but may act as the solution you require.

import copy
import pprint
import pickle

################################################################################

class _Interface:

    def __init__(self, default, database=None):
        self.__default = default
        if database is None:
            self.__database = copy.deepcopy(default)
        else:
            self.__database = database

    def __repr__(self):
        return pprint.pformat(self.__database)

    def __getattr__(self, name):
        attr = self.__default[name]
        if isinstance(attr, dict):
            return _Interface(attr, self.__database[name])
        raise AttributeError(name)

    def __setattr__(self, name, value):
        if name in {'_Interface__default', '_Interface__database'}:
            super().__setattr__(name, value)
        else:
            raise AttributeError(name)

    def __getitem__(self, name):
        item = self.__default[name]
        if isinstance(item, dict):
            raise KeyError(name)
        return self.__database[name]

    def __setitem__(self, name, value):
        item = self.__default[name]
        if isinstance(value, type(item)):
            self.__database[name] = value
        else:
            raise TypeError(type(value))

################################################################################

class Registry(_Interface):

    @property
    def __database(self):
        return self._Interface__database

    def load(self, path):
        with open(path, 'rb') as file:
            data = pickle.load(file)
        self.__merge(data, self.__database)

    @classmethod
    def __merge(cls, source, sink):
        for key, value in source.items():
            if key not in sink:
                sink[key] = value
            elif isinstance(value, type(sink[key])):
                if isinstance(value, dict):
                    cls.__merge(value, sink[key])
                else:
                    sink[key] = value

    def save(self, path):
        with open(path, 'wb') as file:
            pickle.dump(self.__database, file)

################################################################################

file1 = Registry({'hello': ['a', 'b', 'c'],
                  'world': ['d', 'e', 'f'],
                  'foo': ['g', 'h', 'i'],
                  'namespace': {'j': 0,
                                'k': 1,
                                'm': '2',
                                'n': '3'}})

file2 = Registry({'hello': ['a', 'b', 'c'],
                  'world': ['d', 'e', 'f'],
                  'foo': ['g', 'h', 'i'],
                  'namespace': {'j': '4',
                                'k': '5',
                                'm': '6',
                                'n': '7'},
                  'bar': []})

file1['hello'][0] = 'z'
file1.save('mini.db')
file2.load('mini.db')
file2['bar'].extend(['j', 'k', 'l'])

print(file2)
print(file2.namespace['k'])
print(file2.namespace['m'])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM