在這裏記一下使用Python過程中比較雞肋的操作,就是很基礎但又容易忘記還不好谷歌的那種操作。
目錄
Python模塊
重新載入模塊
在Python2.X中,可以通過內置函數reload重新載入模塊。reload可以在模塊被修改的情況下不必關閉Python而重新載入模塊。在使用reload重載入模塊時,該模塊必須事先已經被導入。
在Python3.X中,reload函數已經被刪除,要重新再入模塊,則必須使用imp模塊中的reload函數(如:imp.reload(os) #重新載入os模塊)。
Python在哪裏查找模塊
編寫好的模塊只有被Python找到才能被導入。
在導入模塊時,Python解釋器首先在當前目錄中查找要導入的模塊。如果未找到模塊,則Python解釋器會從sys模塊中path變量指定的目錄中查找導入模塊。如果在以上所有目錄中都未找到導入的模塊,則會輸出出錯信息。
在腳本中可以向sys.path添加模塊查找路徑:
例如:
import os
import sys
modulepath=os.getcwd()+'\\module' #將當前目錄下的module子目錄添加到sys.path中
sys.path.append(modulepath)
print(sys.path)
import mymodule #從moudle目錄中導入mymoudle模塊
是否需要編譯模塊
當調用或運行完一個模塊後,當前目錄下會生成一個編譯成的字節碼文件(.pyc)。
雖然Python是腳本語言,但Python可以將腳本語言編譯成字節碼的形式。對於模塊,Python總是在第一次調用後就將其編譯成字節碼文件,以提高腳本的啓動速度。
對於非模塊的腳本,Python不會在運行腳本後將其編譯成字節碼的形式。如果想將其編譯,可以使用py_compile模塊:
例如:
#file:bianyi.py
#
import py_compile #導入py_compile模塊
py_compile.compile('usemodule.py','usemodule.pyc') #編譯 usemodule.py
注意:在Python3中,如果在py_compile.compile函數中不指定第2個參數,則在當前目錄新建一個名爲“pycache”的目錄,並在這個目錄中生成“被編譯模塊名.cpython-32.pyc”的pytc字節碼文件。
腳本優化編譯
可以通過Python的命令行選項將腳本優化編譯。Python編譯的優化選項有兩個:
-O 該選項對腳本的優化不多,編譯後的腳本以“.pyo”爲擴展名。凡是以“.pyo”爲擴展名的Python字節碼都是經過優化的。
-OO 該選項對腳本的優化的程度很大。使用該標誌可以使編譯的Python腳本更小。使用該選項可以導致腳本運行錯誤,因此,謹慎使用。
例如:
>>>python -O compile.py
>>>python -OO compile.py
如何查看模塊提供的函數名
使用內置函數dir()來查看
dir([object]) #object 可選參數,要列舉的模塊名
例如:
>>>import os
>>>dir(os) #獲得os模塊中的名字和函數
或者:
>>>dir() #獲得當前腳本中所有名字列表
Psyco讓 Python 運行得像 C 一樣快
用 Psyco 讓 Python 運行得像 C 一樣快。
這玩意兒沒用過,只是聽說過,以後用到了再學習補充。
參考文章:
https://www.ibm.com/developerworks/cn/linux/sdk/python/charm-28/
得到列表中唯一元素值的最快方法set([1,1])
a = [1,2,3,3,4,5,5,5,5,6]
b = set(a)
b
Python線程
線程概念
幾個概念:
- 線程 — 是程序的執行分支,是程序中真正負責執行業務的地方。
- 多線程 — 類似於同時執行多個不同的程序。
- 併發 — 四百米接力賽
- 並行 — 跑馬拉松
優點:
- 可以把那些長時間處於等待的線程,放到後臺去處理。 下載內容。等待文件。等待網絡請求。等待數據庫
- 給前端增加一些額外的特效。如:下載進度、觸發事件(手機上點擊某個應用的圖標)。
- 讓程序的執行速度更快。如:多線程下載(相當於空間換時間)
線程是包含於進程的。每個線程都有自己的CPU寄存器。稱之爲線程的上下文,用於反應線程上次運行的狀態
Pyhon中的兩種線程
Python中包含兩種線程:
- 內核線程 — 由操作系統內核創建和撤銷的。
- 用戶線程 — 由用戶創建和撤銷的。
Python3中的兩個線程模塊
- threading(推薦使用)
- _thread
在低版本是有thread模塊的,但在python3被廢棄了,使用_thread來代替。
threading提供了幾個函數:
thrading.currentThread() #獲取當前線程變量
thrading.enumerate() #獲取包含當前正在運行的線程的集合(list[]格式)
thrading.activeCount() #獲取當前存活的線程數量,和len(thrading.enumerate())一樣。
Thread類還提供如下函數:
run() # 線程活動的方法
start() #啓動線程
join() #等待至線程中止。 A和B Bjoin A 讓A等待。
isAlive() #判斷線程是否存活
getName() #獲取線程名稱
Python中創建線程的兩種方法
- 用類來包裝線程對象(推薦使用)
- 用函數
_thread 提供了低級別的原始的以及簡單的鎖,不完全,因此它的功能相比threading有限。
1、用類包裝線程對象創建線程(推薦使用)
例如:
import threading
import time
# 設置一個標誌。
exitFlag = 0
# 創建一個數據類型。名字叫做myThread. 該類型繼承threading模塊中的Thread類。
class myThread(threading.Thread):
# 構造方法 用於構造myThread對象。 myThread類型的值。類似於i = 0
def __init__(self, threadID, name, counter):
# 調用父類的構造
threading.Thread.__init__(self)
# 完成參數賦值
self.name = name
self.threadID = threadID
self.counter = counter
# 重寫的方法。線程實際執行的業務都必須放在這。
def run(self):
print("開始線程:{}".format(self.name))
print_curr_time(self.name, self.counter, 5)
print("結束線程:{}".format(self.name))
def print_curr_time(name, delay,counter):
"""
用於打印當前時間
:param name: 線程的名稱
:param delay: 延遲的時間
:return:
"""
while counter:
# 讓當前休眠。休眠delay的時間
if exitFlag:
name.exit()
time.sleep(delay)
print("{}\t{}".format(name, time.ctime(time.time())))
counter -= 1
# 創建新線程
thread1 = myThread(1,"一隻王八",1)
thread2 = myThread(2,"豈不美哉",2)
# 啓動線程
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print("退出主線程")
執行結果:
開始線程:一隻王八
開始線程:豈不美哉
一隻王八 Fri Dec 28 17:50:06 2018
豈不美哉 Fri Dec 28 17:50:07 2018
一隻王八 Fri Dec 28 17:50:07 2018
一隻王八 Fri Dec 28 17:50:08 2018
豈不美哉 Fri Dec 28 17:50:09 2018
一隻王八 Fri Dec 28 17:50:09 2018
一隻王八 Fri Dec 28 17:50:10 2018
結束線程:一隻王八
豈不美哉 Fri Dec 28 17:50:11 2018
豈不美哉 Fri Dec 28 17:50:13 2018
豈不美哉 Fri Dec 28 17:50:15 2018
結束線程:豈不美哉
退出主線程
線程鎖的用法
上面執行結果順序有點“亂”,想要讓線程按規定順序執行的話就需要用到“鎖”了。
這裏的“鎖”並不是指給資源加鎖,而是用鎖去鎖定資源,你可以定義多個鎖, 當你需要獨佔某一資源時,任何一個鎖都可以鎖這個資源。這和你用不同的鎖都可以把相同的一個門鎖住是一個道理。
【注意】這個鎖是不被某個特定線程所擁有的。一個線程獲取了鎖,之後任何線程嘗試着獲取鎖,都會失敗,包括這個獲取了鎖的線程自己嘗試獲取鎖。
#創建鎖
mutex = threading.Lock()
#鎖定
mutex.acquire(blocking = True, timeout = -1)
"""
返回的是True或者False,分別代表成功和失敗。
默認的兩個參數:
1、blocking=True,意思是調用方法的時候沒有獲取到鎖,就會堵塞線程,直到獲取到鎖爲止。
2、timeout=-1,表示等待獲取鎖的時間,-1表示一直等待。如果超過timeout設定的時間還沒有獲取到鎖就會返回獲取鎖失敗。
【注意】如果設定了timeout爲正數,則不能設定blocking=False。因爲設定了timeout爲正數表明等待設定的時間會阻塞線程,和blocking=False是矛盾的。
"""
#釋放
mutex.release()
代碼舉慄:
交替打印ABC,A由一個線程打印 ,B由一個線程打印,C由一個線程打印。
import threading
def work_1():
for i in range(5):
mutex1.acquire()
print("A")
try:
mutex2.release()
except:
pass
def work_2():
for i in range(5):
mutex2.acquire()
print("B")
try:
mutex3.release()
except:
pass
def work_3():
for i in range(5):
mutex3.acquire()
print("C")
try:
mutex1.release()
except:
pass
if __name__ == '__main__':
mutex1 = threading.Lock()
mutex2 = threading.Lock()
mutex3 = threading.Lock()
t1 = threading.Thread(target=work_1)
t2 = threading.Thread(target=work_2)
t3 = threading.Thread(target=work_3)
t1.start()
t2.start()
t3.start()
t1.join()
t2.join()
t3.join()
執行結果:
A
B
C
A
B
C
A
B
C
A
B
C
A
B
C
關於鎖還有一些內容,可以參考一下這篇文章:《threading中的鎖》
2、函數式創建線程
_thread.start_new_thread(function,args,[kwargs])
# function: 線程函數
# args:傳遞給線程的參數。必須是tuple類型
# []代表可選
例如:
import _thread
import time
def print_curr_time(name,delay):
"""
用於打印當前時間
:param name: 線程的名稱
:param delay: 延遲的時間
:return:
"""
count = 0
while count < 5:
# 讓當前休眠。休眠delay的時間
time.sleep(delay)
count += 1
print("{}\t{}".format(name,time.ctime(time.time())))
# 創建線程
try:
#括號內放的是希望thread去執行的函數
_thread.start_new_thread(print_curr_time ,("Thread-1",2))
_thread.start_new_thread(print_curr_time ,("Thread-2",4))
except Exception:
print("Error: 無法啓動線程")
執行結果如下:
Thread-1 Fri Dec 28 17:38:24 2018
Thread-2 Fri Dec 28 17:38:26 2018
Thread-1 Fri Dec 28 17:38:26 2018
Thread-1 Fri Dec 28 17:38:28 2018
Thread-2 Fri Dec 28 17:38:30 2018
Thread-1 Fri Dec 28 17:38:30 2018
Thread-1 Fri Dec 28 17:38:32 2018
Thread-2 Fri Dec 28 17:38:34 2018
Thread-2 Fri Dec 28 17:38:38 2018
Thread-2 Fri Dec 28 17:38:42 2018
故障
Anaconda使用時出現的代理錯誤解決辦法
剛纔想用conda創建一個虛擬環境,結果老是出現代理錯誤,如下圖:
以前遇到這種情況,一般是換個好點的網速,或者換個鏡像。然而這次並沒什麼用。仔細一看才知道是代理有錯。
解決方案如下:
右擊桌面的網絡圖標–>屬性–>選擇“連接”選項卡;
找到局域網設置,把下面的代理服務器勾號去掉,改爲“自動檢測設置”打勾。應用即可。
總是出現python庫安裝不上的情況
安裝python庫的時候可能會出現以下情況:
勾去代理的方法也不管用,而且安裝其他的python庫也會出現這種情況。
解決方案1:
找到internet選項重置一下:
解決方案2:
換一個連接
Python的函數參數按值還是按引用傳遞參數?
詳情見官方文檔:
http://www.runoob.com/python/python-functions.html
這裏只說一個我碰到的例子:
def tst(a):
a.append([1,2,3])
print('函數tst中的列表a是:',a)
pass
x = ['q','w','e']
tst(x)
print('函數tst外的列表x是:',x)
輸出:
函數tst中的列表a是: ['q', 'w', 'e', [1, 2, 3]]
函數tst外的列表x是: ['q', 'w', 'e', [1, 2, 3]]
從上面現象我們知道,函數在改變形參a
的同時居然也把實參x
也給改變了!
然後我又去找了一些資料才知道,在python中,strings, tuples, 和numbers是不可更改的對象,而list,dict等則是可以修改的對象。
然後我又試了一下numpy.array
,也是可修改的。
如果想在改變形參的同時又不改變實參,可以這麼做:
def tst(a_):
a = a_.copy() #copy一下形參接受到的值並賦給變量a
a.append([1,2,3])
print('函數tst中的列表a是:',a)
pass
x = ['q','w','e']
tst(x)
print('函數tst外的列表x是:',x)
輸出結果:
函數tst中的列表a是: ['q', 'w', 'e', [1, 2, 3]]
函數tst外的列表x是: ['q', 'w', 'e']