Python中可選的環境變量設置,Python中如何使用pdb調試腳本


好記性不如爛筆頭,看到Python Optional Variables這一塊,把學習的東西記錄下來



一. 可選的環境變量設置

會寫Java Hello World的同學一定知道如何設置環境變量,比如:JAVA_HOME,CLASSPATH等。


Python中也一樣有類似的環境變量,有一些還是可選的(比如:PYTHONPATH, PYTHONSTARTUP等)

  1. 設置PYTHONPATH

這個環境變量有什麼用呢?

我們知道在導入模塊時(比如:import some_module_name),Python需要在某些路徑(即sys.path這個列表中的路徑)中去尋找相應的模塊,而PYTHONPATH這個變量就是告訴Python,將它的值也加入到搜索路徑中(即將PYTHONPATH的值合併到sys.path列表中)。

export PYTHONPATH=/tmp
python -c "import sys; print 'found' if '/tmp' in sys.path else '' "

輸出結果是:found

說明/tmp在sys.path中被找到了(即/tmp附加到了sys.path中)


2. 設置PYTHONSTARTUP

如果這個環境變量的值是一個可讀的文件,那麼該文件中的Python命令會在交互模式啓動之前執行。

echo "print 'hello world'" > /tmp/a.py
export PYTHONSTARTUP=/tmp/a.py
python

在啓動python交互模式後,會看到有hello world已經被輸出了。


3. 設置PYTHONHOME

一般在這個變量沒有被設置的情況下,Python中的sys.path會列出一些模塊的搜索路徑。

# 比如:
['', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-linux2', 
'/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', 
'/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', 
'/usr/lib/python2.7/dist-packages']

Python模塊的搜索路徑一般默認是sys.prefix/lib,可以看到很多路徑是 /usr/lib/... 這種,其中/usr 就是sys.prefix這個變量的值(windows上可能是你安裝Python的目錄,比如: C:\Python2.7)。

如果人工指定了PYTHONHOME,那麼sys.prefix的值就會被替換。


隨便替換PYTHONHOME的值,可能造成Python無法啓動,替換前請備份sys.prefix的值



4. 設置PYTHONCASEOK

這個變量只對Windows起效,可以設置爲任意的值(比如:SET PYTHONCASEOK=OK)

設置了以後,Python對模塊的導入,將忽略大小寫(只對用戶module忽略大小寫,對built-in module還是大小寫敏感)



5. 設置PYTHONIOENCODING

看這個名字,IO Encoding可以猜到這個東西是和輸入輸出有關的。對,這個環境變量的作用就是指定Python程序標準輸入輸出(stdin,stdout,stderr)的編碼。

關於這個東西的運用,請參考:http://www.soimort.org/posts/118/  太長不看 :D


再補充一些關於encode和decode的要點:

在Python 2.x中,str類型的字符串,都是指string of bytes(二進制流的表示形式),一般來說

1). '...'.decode([encoding_name])是將string of bytes轉化成unicode string

運用場景是,從網絡或者文件中讀取了二進制流,然後將其轉化爲unicode字符串,便於閱讀。


2). u'....'.encode([encoding_name])是將unicode string轉化成string of bytes

運用場景是,將unicode字符串轉化成二進制流(Java的叫法也稱爲字節流),然後推向網絡或者文件中。


另外,還有兩個方法,str.encode和unicode.decode,這兩個方法意義不大(幾乎很少運用)

"...".encode() 會先默認隱式的用default encoding去decode,即調用"...".decode(sys.getdefaultencoding()) ,然後再繼續調用"...".encode()



而u"...".decode()也會先默認隱式的調用u"...".encode(sys.getdefaultencoding()),然後繼續調用u"...".decode()



二. 使用pdb模塊調試、跟蹤腳本

有些時候,需要在沒有IDE幫助的情況下,對腳本的運行情況進行調試、跟蹤,可以使用Python內置的pdb模塊(參考:https://docs.python.org/2/library/pdb.html)

一個簡單的例子:

對腳本test.py進行跟蹤調試

#! /usr/bin/env python

def foo():
    s = 0
    for i in range(3):
        s += i
    print s


if __name__ == "__main__":
    foo()

運行命令:

python -m pdb test.py

顯示類似如下所示:

> /tmp/test.py(3)<module>()
-> def foo():
(Pdb) l
  1      #! /usr/bin/env python
  2      
  3  ->    def foo():
  4          s = 0
  5          for i in range(3):
  6              s += i
  7          print s
  8      
  9      
 10      if __name__ == "__main__":
 11          foo()
(Pdb) n
> /tmp/test.py(10)<module>()
-> if __name__ == "__main__":
(Pdb)


(pdb)是調試提示符,在提示符下可以輸入命令(具體參考文檔

可以在(pdb)提示符下,查看標量的值,可以使用print 語句打印


常用的簡單命令有:

命令全稱
簡寫
命令描述

list
l
列出當前執行腳本的內容(其中有箭頭標註當前執行到的位置)

next
n
執行下一步,遇到函數不進入其內部。(相當於IDE中的step over)

step
s
執行下一步,遇到函數進入其內部。(相當於IDE中的step into)

break
b

設置斷點,如果不帶參數,則列出當前執行腳本中的所有斷點(號)。


也可以帶參數,比如,執行: b 6)代表在腳本的第6行設置斷點,如右邊所示,它的斷點號是1。

(Pdb) b 6
Breakpoint 1 at /tmp/test.py:6
(Pdb) l
  5          for i in range(3):
  6 B            s += i
  7          print s
  8      
  9      
 10  ->    if __name__ == "__main__":
 11          foo()
clear
cl

清除腳本中的斷點。

1)不帶參數,會詢問是否清除腳本中的所有斷點


2)帶參數會清除指定的斷點。(注意清除的格式)


  • cl(ear) [filename:lineno | bpnumber [bpnumber ...]]

    With a filename:lineno argument, clear all the breakpoints at this line. With a space separated list of breakpoint numbers, clear those breakpoints. Without argument, clear all breaks (but first ask confirmation).


所以,要清除上面設置的第6行的斷點,要麼使用  cl 1  (清除斷點號是1的斷點);要麼使用  cl test.py:6 (清除test.py中的第6行)


使用 cl 6是錯誤的,因爲目前爲止,沒有標號是6的斷點!!

continue
c
繼續執行腳本,直到遇到斷點停止。

quit
q
退出調試




That's it!w_0050.gif

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章