2015-01-04 32 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

相關問題