2015-01-04 77 views
3

我对Python有点新(但完全没有编程,已经流利地在Perl,PHP,& Ruby中)。 我遇到了所有以前的语言和Python之间的主要区别:主要是我可以轻松地将数据从另一个文件读入整个项目。 这里有两个主要的例子,我想解决:整个Python应用程序的一个配置文件

1)我想有一个设置/配置文件(在YAML中),读取并在config.py文件中解析。然后我想要一个生成的dict()可以被我的其他文件在项目中访问。我已经想出了如何通过from lib.project.config import cfg这样做,但这意味着对于导入配置的每个页面,系统必须重新分析yaml。这对我来说似乎很愚蠢。有没有办法让这个文件解析一次,然后让结果可以访问我的项目中的任何其他文件?

2)我想导入一个database.py文件,然后查看我的配置,看看我们是否需要导入sqlite3,mysql或postgresql版本的数据库类。再次,我可以通过将逻辑直接放入每个需要数据库类的页面来管理。但我讨厌粘贴代码,如

if cfg.get('db_type') == 'sqlite': 
    from lib.project.databases.sqlite3 import database 
elif cfg.get('db_type') == 'mysql': 
    from lib.project.databases.mysql import database 

位于需要数据库类的每个文件的顶部。我宁愿增加:

​​

任何帮助将非常感激。 我已经做了大量的搜索和SO搜索,没有找到我的答案。希望你们中的一个能够帮助你。

谢谢。

更新: 我这样做的原因(对于#2)是因为我也试图让其他类继承数据库类。 所以lib/project/databases/sqlite.py是数据库类的定义。 所以是lib/project/databases/mysql.py。 的想法是,这个导入完成后我可以导入类,如用户类,并定义它像这样:

class user(database): 
    ... 

并由此继承了所有的结构和数据库类的方法。 你的建议是简单地创建一个基于sqlite/mysql逻辑/决策的实例,然后将它传递到需要的地方,这是一个很好的解决方案。但我需要更多... 想法?

+1

模块在每次导入时都不会执行。第一次导入的结果保存在一个'sys.modules'字典中。在随后导入同一模块时,缓存的值将被简单地返回而不是再次运行。这意味着,如果您读取模块主代码中的配置文件并将结果保存在全局模块变量中,则只会发生一次。给定模块的所有导入器都可以简单地引用变量及其结果(或模块函数)。 – martineau 2015-01-04 11:55:01

+0

Thanks @maartineau,要清楚:这是否意味着我仍然需要导入每个需要它的文件的配置文件(了解到它实际上并未每次都进行REparsed)?如果我必须在每个文件上导入,这似乎不是什么大问题,只是看起来过分。在完成顶层文件的导入之后,我们很想在每个页面上执行诸如config.settings ['path']之类的操作。 – loqqi 2015-01-04 12:13:08

+1

如果你导入了'config',那么你应该可以引用'config.settings ['path']'假设在运行模块的顶层时定义了一个settings字典(这很容易去做)。你可以让事情看起来像内置的 - 所以'import'甚至不需要 - 但是这样做是不鼓励的。 – martineau 2015-01-04 12:31:56

回答

1

1)你全都设置 - 文件只能被读取一次。

2)同意你不想复制任何粘贴代码这样的 - 如果你想用整个项目的数据库的1个实例,你会做这样的事情:

import lib.project 

db = lib.project.database 

其中db只是一个局部变量,用于访问已经创建的数据库。您将在lib/project/databases.py中将您的数据库实例化为database(如您对if/elif代码所做的解决方法是否使用sqlite3或mysql),然后在您的lib/project/__init__.py文件中执行from .databases import database

,如果你想在你的项目中使用多个数据库(在相同的sqlite3/MySQL的类型),你会解决它的构造Database势必(或继承)在databases.py

from lib.project.Config import config 
if config.db_type == 'sqlite' : 
    import lib.project.databases.Sqlite as Db 
elif config.db_type == 'mysql': 
    import lib.project.databases.Mysql as Db 

class Database(Db): 
    '''docs''' 
+0

我会更进一步,并将库类模块内的db类的实例化,并简单地导入实例。 – 2015-01-04 13:03:16

+0

@DanielRoseman好主意 - 编辑了我的答案 – gnr 2015-01-04 13:12:21

+0

谢谢你们。如果我只想要一个数据库类的实例,那将是一个很好的解决方案...... :(我以这种方式来做事情的原因(对于#2)是因为我也试图让其他类继承数据库类。查看我更新的问题以获取更多详细信息。 – loqqi 2015-01-04 23:15:43

0

谢谢所有这些信息都可以帮助您更好地了解Python以及如何获得我正在寻找的东西。

这里是我落得这样做:

1)配置文件问题: 这显然是主要解决的开始。我确认了每个人都在说的话:你可以随意“导入”一个文件,但是它只能被解析/处理/编译一次。至于使其可达任何需要它的文件:想要使用它

import os 
import yaml 

class Config: 

    def __init__(self): 
     self.path = os.getcwd() 
     stream = open(self.path+"/conf/config.yaml", 'r') 
     data = yaml.load(stream) 
     config_keys = data.keys() 
     for k in config_keys: 
      setattr(self, k, data.get(k)) 
     if (os.path.isfile(self.path+"/conf/config-override.yaml")): 
      stream = open(self.path+"/conf/config-override.yaml", 'r') 
      data = yaml.load(stream) 
      config_keys = data.keys() 
      for k in config_keys: 
       setattr(self, k, data.get(k)) 

config = Config() 

然后任何文件: 配置类

from lib.project.Config import config 

这是所有工作顺顺当当至今。

2)数据库类动态数据库类型: 我只是改变了我的整个设计一点点做一个数据库类(大部分是空的),无论从SQLite的或MySQL类继承(包括自定义构建它们包装现有SQLITE3和mysql连接器类)。这种方式总是有一个可靠的数据库类继承,我只加载需要的文件,而且全部由我的配置文件定义。例如: 数据库类:

from lib.project.Config import config 
if config.db_type == 'sqlite' : 
    from lib.project.databases.Sqlite import Sqlite 
elif config.db_type == 'mysql': 
    from lib.project.databases.Mysql import Mysql 

class Database(Sqlite if config.db_type == 'sqlite' else Mysql): 
''' documentation ''' 

我仍然希望听到人们对这个代码/方法的反馈。正如我所说的,我对Python仍然很陌生,可能仍然缺少一些东西。

再次感谢大家。

+0

请参阅我对#2的回答中的编辑。#1看起来不错,我建议尽管我)模块的小写名称('config.py',而不是'Config.py')和ii)调用你的类'_Config'而不是'Config','_'表示该类是“私人”的,不鼓励使用该类(并且任何查看代码的人都知道使用“config”实例)。 – gnr 2015-01-06 13:28:30

相关问题