摘要:首先假設是一個包名或者模塊名非對象名。參數可以為或者字節碼對象,返回。這里可以理解為解釋字節碼,并將字節碼執行過程中的全局變量存入字典中。
import_string
先來分析一下這個動態導入函數:werkzeug.utils.import_string
def import_string(import_name, silent=False): """基于字符串動態導入對象。字符串有兩種形式寫法用點來分割對象名(``xml.sax.saxutils.escape``)和用冒號來分割對象名 (``xml.sax.saxutils:escape``). silent決定發生異常時是返回None還是拋出一些異常(安靜,挺形象的。) """ import_name = str(import_name).replace(":", ".") try: try: #首先假設import_name是一個包名或者模塊名(非對象名)。 __import__(import_name) except ImportError: if "." not in import_name: #沒有點說明即使我們假設錯誤,也沒法繼續嘗試。故而立即拋出異常 raise else: #如果導入正確,那么可以從sys.modules字典里面獲取已經導入的模塊或包. #為什么要通過sys.modules[import_name]返回而不是直接return __import__(import_name)呢?因為__import__在沒有提供fromlist參數時,返回值策略為返回第一個點之前的頂級包對象,比如"os.path"返回的是os而不是os.path. return sys.modules[import_name] #如果import_name不是包名或模塊名,而是具體的對象、函數名。 module_name, obj_name = import_name.rsplit(".", 1) try: #相當于from module_name import obj_name module = __import__(module_name, None, None, [obj_name]) except ImportError: #如果支持的模塊沒有被父模塊設置好的情形中會導入失敗,這時需要先導入父模塊(或包)。典型的例子就是logging與logging.config。 module = import_string(module_name) try: #通過getarr從模塊中返回具體對象 return getattr(module, obj_name) except AttributeError as e: raise ImportError(e) except ImportError as e: if not silent: reraise( ImportStringError, ImportStringError(import_name, e), sys.exc_info()[2])flask.config模塊
import os import types import errno from werkzeug.utils import import_string from ._compat import string_types, iteritems from . import json class Config(dict): """config類除了正常的dict職責外,還具有從py文件(模塊)、對象或字典填充值的能力。 from_envvar會調用from_pyfile會調用from_object,另還有from_json會調用from_mapping 還有一個便利的get_namespace方法。 """ def __init__(self, root_path, defaults=None): # root_path查找py文件的基路徑。 dict.__init__(self, defaults or {}) self.root_path = root_path def from_envvar(self, variable_name, silent=False): """variable_name是一個環境變量名,指向一個py文件。返回bool值,是否加載填充成功。 """ rv = os.environ.get(variable_name) #...省略部分校驗邏輯... #這里調用from_pyfile return self.from_pyfile(rv, silent=silent) def from_pyfile(self, filename, silent=False): filename = os.path.join(self.root_path, filename) #利用標準庫types來動態創建一個模塊對象,名為config,文件屬性(__file__)指向設置為前面的filename d = types.ModuleType("config") d.__file__ = filename try: with open(filename) as config_file: #exec,compile都是內置函數。 #exec(object[, globals[, locals]]) 參數object可以為str或者字節碼對象,返回None。這里可以理解為解釋字節碼,并將字節碼執行過程中的全局變量存入d.__dict__字典中。 #compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1) #compile用于動態編譯文件為字節碼對象,其中"exec"為編譯模式,代表整個文件(多行)編譯,其余模式還有"eval"單行語句編譯,"single"單行交互式語句編譯。 exec(compile(config_file.read(), filename, "exec"), d.__dict__) except IOError as e: ...略pass... #這里調用from_object,from_object才是關鍵。 self.from_object(d) return True def from_object(self, obj): """參數obj可以是str(需要被導入的對象)或者一個對象。它只允許模塊或對象中的大寫屬性填充進來,小寫的忽略。 你可以這樣來使用本方法 app.config.from_object("yourapplication.default_config")或者 from yourapplication import default_config app.config.from_object(default_config) """ if isinstance(obj, string_types): obj = import_string(obj) for key in dir(obj): if key.isupper(): #只允許模塊或對象中的大寫屬性填充進來,小寫的忽略。 self[key] = getattr(obj, key) def from_json(self, filename, silent=False): """filename是json文件名。這是flask0.11添加的方法。 """ filename = os.path.join(self.root_path, filename) try: with open(filename) as json_file: obj = json.loads(json_file.read()) #注意,如果不知道json.loads的type參數,那么默認加載為字典。即obj是一個字典 except IOError as e: ...略pass... return self.from_mapping(obj) #這里調用from_mapping def from_mapping(self, *mapping, **kwargs): """行為類似于dict的update方法,只不過忽略小寫屬性.flask0.11添加的方法 """ mappings = [] if len(mapping) == 1: if hasattr(mapping[0], "items"): mappings.append(mapping[0].items()) else: mappings.append(mapping[0]) elif len(mapping) > 1: raise TypeError( "expected at most 1 positional argument, got %d" % len(mapping) ) mappings.append(kwargs.items()) for mapping in mappings: for (key, value) in mapping: if key.isupper(): self[key] = value return True def get_namespace(self, namespace, lowercase=True, trim_namespace=True): """返回一個字典,這個字典包含該命名空間的items。這個命名空間是以_作為分隔標識的.比如 app.config["IMAGE_STORE_TYPE"] = "fs" app.config["IMAGE_STORE_PATH"] = "/var/app/images" app.config["IMAGE_STORE_BASE_URL"] = "http://img.website.com" image_store_config = app.config.get_namespace("IMAGE_STORE_") 結果 `image_store_config` 會是這樣:: { "type": "fs", "path": "/var/app/images", "base_url": "http://img.website.com" } 當需要利用這個進行傳參時是比較方便的。 trim_namespace參數為True時,行為就是上面所述,為False時返回的key會包含namespace前綴。 """ rv = {} for k, v in iteritems(self): if not k.startswith(namespace): continue if trim_namespace: key = k[len(namespace):] else: key = k if lowercase: key = key.lower() rv[key] = v return rv def __repr__(self): return "<%s %s>" % (self.__class__.__name__, dict.__repr__(self)) config模塊閱讀配置到此結束,下一篇主題待定。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/38364.html
摘要:帶附件的郵件有時候,我們發郵件的時候需要添加附件,比如文檔和圖片等,這也很簡單,代碼如下郵件服務器地址郵件服務器端口啟用上面的代碼中,我們通過打開了本機的某張圖片,然后通過方法將附件內容添加到對象。 前往本文博客 簡介 給用戶發送郵件是 Web 應用中最常見的任務之一,比如用戶注冊,找回密碼等。Python 內置了一個 smtplib 的模塊,可以用來發送郵件,這里我們使用 Flask...
原文地址: http://52sox.com/write-a-flask-plugin-for-ueditor/ 近期項目開發中,隔壁那個搞python的哥們竟然笑著對我說,希望我能給他寫1個百度編輯器的demo,方便他直接調用。 當時真的受寵若驚,這哥們實力不在我之下,只能答應它了。上網搜索下,有1篇文章Flask項目集成富文本編輯器UEditor實現圖片上傳功能已經有1個現成的例子了。 這...
原文地址: http://52sox.com/write-a-flask-plugin-for-ueditor/ 近期項目開發中,隔壁那個搞python的哥們竟然笑著對我說,希望我能給他寫1個百度編輯器的demo,方便他直接調用。 當時真的受寵若驚,這哥們實力不在我之下,只能答應它了。上網搜索下,有1篇文章Flask項目集成富文本編輯器UEditor實現圖片上傳功能已經有1個現成的例子了。 這...
摘要:簡介官網上對它的定位是一個微開發框架。另外一個必須理解的概念是,簡單來說就是一套和框架應用之間的協議。功能比較豐富,支持解析自動防止攻擊繼承變量過濾器流程邏輯支持代碼邏輯集成等等。那么,從下一篇文章,我們就正式開始源碼之旅了 文章屬于作者原創,原文發布在個人博客。 flask 簡介 Flask 官網上對它的定位是一個微 python web 開發框架。 Flask is a micro...
摘要:官方示例第一行類對象,這個無需解釋。請求對象的端點請求視圖函數的參數通過源碼的注釋我們可以知道,都只是對庫的進行了一層包裝并加入一些屬性。接下來會有更多關于和相關文章放出來,敬請期待參考文檔項目源碼版本注釋版 Flask 是一個 Python 實現的 Web 開發微框架, 有豐富的生態資源。本文從一段官方的示例代碼通過一步步打斷點方式解釋 Flask 內部的運行機制,在一些關鍵概念會...
閱讀 1572·2021-11-25 09:43
閱讀 2476·2019-08-30 15:54
閱讀 2938·2019-08-30 15:53
閱讀 1087·2019-08-30 15:53
閱讀 747·2019-08-30 15:52
閱讀 2538·2019-08-26 13:36
閱讀 807·2019-08-26 12:16
閱讀 1210·2019-08-26 12:13