Python隨筆記

在這裏記一下使用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線程

線程概念

幾個概念:

  • 線程 — 是程序的執行分支,是程序中真正負責執行業務的地方。
  • 多線程 — 類似於同時執行多個不同的程序。
  • 併發 — 四百米接力賽
  • 並行 — 跑馬拉松

優點:

  1. 可以把那些長時間處於等待的線程,放到後臺去處理。 下載內容。等待文件。等待網絡請求。等待數據庫
  2. 給前端增加一些額外的特效。如:下載進度、觸發事件(手機上點擊某個應用的圖標)。
  3. 讓程序的執行速度更快。如:多線程下載(相當於空間換時間)

線程是包含於進程的。每個線程都有自己的CPU寄存器。稱之爲線程的上下文,用於反應線程上次運行的狀態

Pyhon中的兩種線程

Python中包含兩種線程:

  1. 內核線程 — 由操作系統內核創建和撤銷的。
  2. 用戶線程 — 由用戶創建和撤銷的。

Python3中的兩個線程模塊

  1. threading(推薦使用)
  2. _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中創建線程的兩種方法

  1. 用類來包裝線程對象(推薦使用)
  2. 用函數

_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創建一個虛擬環境,結果老是出現代理錯誤,如下圖:
1

以前遇到這種情況,一般是換個好點的網速,或者換個鏡像。然而這次並沒什麼用。仔細一看才知道是代理有錯。

解決方案如下:
右擊桌面的網絡圖標–>屬性–>選擇“連接”選項卡;

2

找到局域網設置,把下面的代理服務器勾號去掉,改爲“自動檢測設置”打勾。應用即可。
3

總是出現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']
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章