###項目結構html
model.py 項目關鍵的類python
util.py 項目幫助文件git
api.py 開放的apigithub
main.py 項目的啓動腳本api
###0 __init__.py文件 python 的模塊是經過__init__.py文件組織,當用戶import module時,該文件自動執行。網絡
""" XXX library ~~~~~~~~~~~~~~~~~~~~~ how to use usage: >>> print "ok" ok """ __title__ = '' __version__ = '1.0.0' __author__ = 'jchluo' #__license__ = 'Apache 2.0' #__copyright__ = '' #import api from .model import ToyModel # Set default logging handler to avoid "No handler found" warnings. import logging try: # Python 2.7+ from logging import NullHandler except ImportError: class NullHandler(logging.Handler): def emit(self, record): pass logging.getLogger(__name__).addHandler(NullHandler())
分爲四部分,分別是註釋、元數據、公開API、其餘操做。session
提供模塊名、描述等信息和簡單的使用樣例,以方便用戶使用。app
使用樣例應該遵循doctest包的格式,以進行自動化測試。格式是post
- ">>> "表示輸入,注意:>>>後面的一個空格必須
- 下一行表示期待的輸出
- 注意:樣例必須寫在源文件、方法或者類的開頭
- 測試的命令
python -m doctest -v your_module.py
例如著名的網絡模塊requests使用樣例以下測試
""" usage: >>> import requests >>> r = requests.get('https://www.python.org') >>> r.status_code 200 >>> 'Python is a programming language' in r.content True """
提供包的標題、版本號、做者等信息,若是是開源模塊,最好提供licence和copyright.
在這裏import
你但願用戶使用的類和方法,用戶代碼經過包的名字直接訪問。
例如著名的網絡模塊requests公開的部分API以下
from .models import Request, Response, PreparedRequest from .api import request, get, head, post, patch, put, delete, options from .sessions import session, Session
當用戶須要使用get
方法時,能夠經過
>>>import requests >>>r = request.get("http://www.baidu.com")
代碼中requests
的 get
方法就是經過from .api import get
導進來的。 若是不在這裏import
,即必須
>>>import requests.api >>>r = request.api.get("http://www.baidu.com")
不在這裏import
有不少缺點。
一、用戶使用不方便,容易出錯,經過import
具體的api
包來調用方法。
二、泄露了requests
的具體實現。假設未來有更好的訪問網絡方式,api
過期,可是requests
不能刪除api
模塊,由於用戶的代碼中都寫了api
包,一旦刪除了,用戶代碼所有出錯。
三、用戶可能會調用api
的私有方法,致使程序出錯。由於私有方法是內部使用的。
這裏提供一些logging
和 warnings
的配置。
咱們進行一些重要的操做時,通常經過打log的方式以進行記錄,以方便後續的分析等。
request
包的底層urllib3的connectionpool.py是這樣打log
:
>>> import logging >>> log = logging.getLogger(__name__) >>> log.warn("Get xxx ") No handlers could be found for logger "__main__"
嘗試一下就會發現,這時會提示第4行的"No handlers"的提示。
這是由於若是沒有配置好log的handler信息,log不知道怎麼處理這個warn信息。
**通常來講,咱們但願log的配置由用戶的代碼來控制。由用戶來決定打log的格式,輸出的位置,是到文件仍是屏幕。**因此模塊包通常不對log進行配置。
模塊包須要對log進行操做,例如log.warn("xxx")
,可是又不能配置log的輸出位置,因而就有上面No handler
的提示。
爲了沒有上面的提示,模塊包只好給log配置了一個空handler
,這個hander
什麼都不作,只是佔位,由於有了hander
, 因此提示就再也不出現了。同時,若是用戶配置了log,就會把這個空handler
覆蓋,採用了用戶的配置。下面代碼 是模塊包配置的空handler
import logging try: # Python 2.7+ from logging import NullHandler except ImportError: class NullHandler(logging.Handler): def emit(self, record): pass logging.getLogger(__name__).addHandler(NullHandler())
假設用戶本身處理log, 能夠輸入如下代碼
>>> import logging >>> logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s', filename='myapp.log') >>> import requests >>> requests.get("http://www.baidu.com")
注意:上面是用戶的代碼,不是模塊包的代碼
這時候,urlllib3
的 log就打到了文件myapp.log
2015-12-19 22:07:36,032 DEBUG "GET / HTTP/1.1" 200 None
###1 類
###2 方法