我學習python過程, 和學習其它編程知識一樣, 不是先讀大部頭書系統學習, 而是看博客和直接實踐, 慢慢將這些知識點連成線, 再擴展到面. 這個過程缺點和優點都很明顯. 缺點是, 有些知識點可能因為一直沒有機會碰到, 就一直是盲點, 另外從點到面過程較長. 好在我自學能力很強, 基本碰到的問題都能搞得定.
近期研究github開源項目有幾個發現, 代碼多帶有:
2. from __future__ import unicode_literals
3. 在根package的 __init__.py, 加上版本號和作者等信息,
__version__ = '0.0.2'
__author__ = 'somebody'
4. 如果源碼保存為utf-8格式, 文件頭加上如下注釋,
# -*- coding: utf-8 -*-
==============================
__future__的absolute_import
==============================
from __future__ import absolute_import, 字面理解好像是僅僅允許絕對引用, 其實不然, 真實意思是禁用 implicit relative import, 但並不會禁掉 explicit relative import.
舉個例子, 目錄結構如下,
src -my_app -__init__.py -cake |- __init__.py |- icing.py |- sponge.py -drink |- __init__.py |- water.py
要在 sponge.py 引用 icing , 有多種方法:
1. import icing # implicit relative import, py2已強烈不推薦使用, py3已經不可用了.
2. from . import icing # explicit relative import, python.org 官方不推薦.
3. from cake import icing # absolute import, python 官方推薦.
總結一下, 最好的做法應該是:
(1) 將 src 目錄加到 PYTHONPATH 中
(2) 在 src 目錄下家里一個 root package, 比如名稱就叫 my_app
(3) import 時候都用 my_app.subpackage 或 my_app.module 這樣絕對路徑的寫法,
比如 import my_app.module 或 from my_app import module
--------------------------
使用absolute_import, 常碰到的一個問題
--------------------------
使用__future__ absolute_import 之后, 常遇到的如下這一問題, 示例:
-PackageA
|- module1.py
|- module2.py
|- __init__.py
module1.py 的代碼示例:
from __future__ import absolute_impact from . import module2 #引入同包下的另一個module if __name__=="__main__": print("module2 was imported in module1.")
運行 module1.py 會報錯, 報錯信息: ValueError: Attempted relative import in non-package.
原因分析: from . import module2 這樣的寫法是顯式相對引用, 這種引用方式只能用於 package 中, 而不能用於主模塊中. 因為[主module]的name總是為 __main__, 並沒有層次結構, 也就無從談起相對引用了.
換句話, if __name__=="__main__": 和相對引用是不能並存的.
解決方法:
方法1: 在 module1 中使用絕對引用, 這個最簡單了, 但相對引用的好處也沒了.
方法2: 使用 python -m 來啟動你的 module1.py, 這個也不推薦.
方法3(推薦): 在 module1 中, 加個main()函數, 然后再新建一個 PackageA/entry.py 做為主程序, 在 entry.py 中使用絕對引用來導入 module1 , 並調用 module1.main(), 這一辦法雖不完美, 但我覺得是最好的方法了.
==============================
unicode_literals
==============================
from __future__ import unicode_literals 在python 2.x中, 對於字符串, 默認還不是采用 unicode 編碼的, 除非在字符串前加上前綴u. 比如:
>>>x='中國' >>>x '\xd6\xd0\xb9\xfa' >>>print(x) 中國 >>> >>>x=u'中國' >>>x u'\u4e2d\u56fd' >>>print(x) 中國
在python3中默認的編碼采用了unicode, 並取消了前綴u. 如果代碼要兼容python2/3, 就很麻煩了.
通常有如下3種做法, 其中前兩個做法都不推薦:
1. 不管是漢字還是英文, 字符串前面統一不加u. 這種處理方式多數情況下沒有問題, 比如print輸出, 但字符串如果需要做encode/decode, 就很麻煩.
2. 加python版本判斷, 如果 sys.version >3 的話, 字符串不加前綴u, 如果是py2, 加上前綴u. 可以想象, 業務邏輯中再加上這樣的判斷, 代碼會變得很難看.
3. 現在有第3種, 即引入unicode_literals, from __future__ import unicode_literals, 這樣在py2下, '中國'這樣的字符串不用家前綴u, 也是unicode編碼.
==============================
引申閱讀
==============================
http://blog.ludovf.net/python-str-unicode/
http://blogs.skicelab.com/maurizio/unicode-common-pitfalls.html
