日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

Python学习笔记(六)

發布時間:2025/5/22 python 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python学习笔记(六) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. IO編程
1.1 文件讀寫
1.2 StringIO和BytesIO
1.3 操作文件和目錄
1.4 序列化
2. 進程和線程
2.1 多進程
2.2 多線程
2.3 ThreadLocal
2.4 進程 vs. 線程
2.5 分布式進程

1. IO編程

輸入和輸出:Input/Output。
同步與異步的區別就在于是否等待IO執行的結果。
回調模式和輪詢模式。

1.1 文件讀寫

在磁盤上讀寫文件的功能是由操作系統提供的,現代操作系統不允許普通的程序直接操作磁盤,所以,讀寫文件就是請求操作系統打開一個文件對象,然后,通過操作系統提供的接口從這個文件對象中讀取數據,或者把數據寫入這個文件。
讀文件

  • >>> f = open('/Users/michael/test.txt', 'r') # 標示符r表示只讀
  • >>> f.read() # 調用read()可以一次讀取文件的全部內容
  • 'Hello, world!'
  • >>> f.close() # 文件使用完畢后必須關閉,因為文件對象會占用操作系統的資源
  • with open('/path/to/file', 'r') as f: # with語句會自動幫我們調用close()方法
  • print(f.read())
  • 調用read()會一次性讀取文件的全部內容,為了保險起見,可以反復調用read(size)方法,每次最多讀取size個字節的內容,或者調用readline()可以每次讀取一行內容,調用readlines()一次讀取所有內容并按行返回list。
    file-like Object
    像open()返回的這種有read()方法的對象,在Python中統稱為file-like Object。StringIO就是內存中創建的file-like Object,常用作臨時緩沖。
    二進制文件

  • >>> f = open('/Users/michael/test.jpg', 'rb') # 要讀取二進制文件,比如圖片,視頻等等,用 rb 模式打開文件
  • >>> f.read()
  • b'\xff\xd8\xff\xe1\x00\x18Exif\x00\x00...' # 十六進制表示的字節
  • 字符編碼

  • >>> f = open('/Users/michael/gbk.txt', 'r', encoding='gbk', errors='ignore') # encoding參數處理非UTF-8編碼的文本文件,errors參數表示如果遇到編碼錯誤后如何處理
  • >>> f.read()
  • '測試'
  • 寫文件
    寫文件和讀文件是一樣的,唯一區別就是調用open()函數時,傳入標示符’w’或’wb’表示寫文本文件或者寫二進制文件。

  • >>> f = open('/Users/michael/test.txt', 'w')
  • >>> f.write('Hello, world!')
  • >>> f.close()
  • with open('/Users/michael/test.txt', 'w') as f: # 要寫入特定編碼的文本文件,在open()傳入encoding參數,將字符串自動轉換成指定編碼
  • f.write('Hello, world!')
  • 1.2 StringIO和BytesIO

    StringIO:在內存中讀寫str。

  • # 寫數據
  • >>> from io import StringIO
  • >>> f = StringIO()
  • >>> f.write('hello')
  • 5
  • >>> f.write(' ')
  • 1
  • >>> f.write('world!')
  • 6
  • >>> print(f.getvalue()) # getvalue()方法用于獲得寫入后的str
  • hello world!
  • # 讀數據
  • >>> from io import StringIO
  • >>> f = StringIO('Hello!\nHi!\nGoodbye!')
  • >>> while True:
  • ... s = f.readline()
  • ... if s == '':
  • ... break
  • ... print(s.strip())
  • ...
  • Hello!
  • Hi!
  • Goodbye!
  • BytesIO:StringIO的操作只能是str,如果要操作二進制數據,就需要使用BytesIO。

  • # 寫數據
  • >>> from io import BytesIO
  • >>> f = BytesIO()
  • >>> f.write('中文'.encode('utf-8'))
  • 6
  • >>> print(f.getvalue())
  • b'\xe4\xb8\xad\xe6\x96\x87'
  • # 讀數據
  • >>> from io import StringIO
  • >>> f = BytesIO(b'\xe4\xb8\xad\xe6\x96\x87')
  • >>> f.read()
  • b'\xe4\xb8\xad\xe6\x96\x87'
  • 1.3 操作文件和目錄

    Python內置的os模塊可以直接調用操作系統提供的接口函數。

  • >>> import os
  • # 操作系統類型,os模塊的部分函數是跟操作系統有關的
  • >>> os.name
  • 'posix'
  • # 獲取系統的詳細信息
  • >>> os.uname()
  • posix.uname_result(sysname='Darwin', nodename='MichaelMacPro.local', release='14.3.0', version='Darwin Kernel Version 14.3.0: Mon Mar 23 11:59:05 PDT 2015; root:xnu-2782.20.48~5/RELEASE_X86_64', machine='x86_64')
  • # 獲取環境變量
  • >>> os.environ
  • environ({'VERSIONER_PYTHON_PREFER_32_BIT': 'no', 'TERM_PROGRAM_VERSION': '326', 'LOGNAME': 'michael', 'USER': 'michael', 'PATH': '/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin:/usr/local/mysql/bin', ...})
  • # 獲取某個環境變量的值
  • >>> os.environ.get('PATH')
  • '/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin:/usr/local/mysql/bin'
  • # 查看當前目錄的絕對路徑:
  • >>> os.path.abspath('.')
  • '/Users/michael'
  • # 在某個目錄下創建一個新目錄,首先把新目錄的完整路徑表示出來:
  • >>> os.path.join('/Users/michael', 'testdir')
  • '/Users/michael/testdir'
  • # 然后創建一個目錄:
  • >>> os.mkdir('/Users/michael/testdir')
  • # 刪掉一個目錄:
  • >>> os.rmdir('/Users/michael/testdir')
  • 合成兩個路徑的時候,不能直接拼接字符串,而是通過os.path.join()函數,這樣可以正確的處理不同操作系統的路徑分隔符。同理,拆分路徑時,通過os.psth.split()函數,這樣可以把一個路徑拆分為兩部分,后一部分總是最后級別的目錄或文件名。

  • # 拆分目錄路徑
  • >>> os.path.split('/Users/michael/testdir/file.txt')
  • ('/Users/michael/testdir', 'file.txt')
  • # 得到文件擴展名
  • >>> os.path.splitext('/path/to/file.txt')
  • ('/path/to/file', '.txt')
  • 文件操作

  • # 對文件重命名:
  • >>> os.rename('test.txt', 'test.py')
  • # 刪掉文件:
  • >>> os.remove('test.py')
  • # 列出當前目錄所有文件
  • >>> [x for x in os.listdir('.') if os.path.isdir(x)]
  • ['.lein', '.local', '.m2', '.npm', '.ssh', '.Trash', '.vim', 'Applications', 'Desktop', ...]
  • 1.4 序列化

    我們把變量從內存中變成可存儲或傳輸的過程稱之為序列化,在Python中叫picking。序列化之后,就可以把序列化后的內容寫入磁盤,或者通過網絡傳輸到別的機器上。反過來把變量內容從序列化對象重新讀到內存里稱之為反序列化,即unpicking。
    Python提供了pickle模塊來實現序列化。

  • >>> import pickle
  • >>> d = dict(name='Bob', age=20, score=88)
  • # 把對象序列化并寫入文件
  • >>> pickle.dumps(d)
  • b'\x80\x03}q\x00(X\x03\x00\x00\x00ageq\x01K\x14X\x05\x00\x00\x00scoreq\x02KXX\x04\x00\x00\x00nameq\x03X\x03\x00\x00\x00Bobq\x04u.'
  • # pickle.dump()直接把對象序列化后寫入一個file-like Object。
  • >>> f = open('dump.txt', 'wb')
  • >>> pickle.dump(d, f)
  • >>> f.close()
  • >>> f = open('dump.txt', 'rb')
  • # piclke.load()方法反序列化對象
  • >>> d = pickle.load(f)
  • >>> f.close()
  • >>> d
  • {'age': 20, 'score': 88, 'name': 'Bob'}
  • JSON
    如果要在不同的編程語言之間傳遞對象,就必須要把對象序列化為標準格式。json表示出來是一個字符串,可以被所有語言讀取,也可以方便的存儲到磁盤或者通過網絡傳輸。
    Python內置的json模塊提供了非常完善的Python對象到JSON格式的轉換。

  • >>> import json
  • >>> d = dict(name='Bob', age=20, score=88)
  • >>> json.dumps(d) # dumps()方法返回一個str,內容就是標準的json
  • '{"age": 20, "score": 88, "name": "Bob"}'
  • 要把json反序列化為python對象,用loads()或者對應的load()方法,前者把json的字符串反序列化,后者從file-like Object中讀取字符串并反序列化。

  • >>> json_str = '{"age": 20, "score": 88, "name": "Bob"}'
  • >>> json.loads(json_str)
  • {'age': 20, 'score': 88, 'name': 'Bob'}
  • 2. 進程和線程

    單核CPU可以執行多個任務,但每個任務都是交替執行的,因為CPU執行速度太快,感覺就像是同時執行一樣。真正并發執行多任務只能在多核CPU上實現,由于任務數量遠多于CPU的核心數量,所以操作系統會自動的把很多任務輪流調度到每個核心上執行。
    對于操作系統,每一個任務就是一個進程。在一個進程內部,要同時干很多事情,就需要同時運行多個“子任務”,這些子任務稱之為線程

    2.1 多進程

    Unix/Linux操作系統提供了一個fork()系統調用,調用一次fork(),返回兩次,因為操作系統把當前進程(父進程)復制一份(子進程),然后分別在子進程和父進程中返回。有了fork()調用,一個進程在接到新任務時就可以復制出一個子進程處理新任務。
    常用的Apache服務器就是由父進程監聽端口,每當有新的http請求,就fork子進程處理任務。
    multiprocessing
    multiprocessing模塊就是跨平臺版本的多進程模塊,它提供了一個Process類來代表一個進程對象。

  • from multiprocessing import Process
  • import os
  • # 子進程要執行的代碼
  • def run_proc(name):
  • print('Run child process %s (%s)...' % (name, os.getpid()))
  • if __name__=='__main__':
  • print('Parent process %s.' % os.getpid())
  • p = Process(target=run_proc, args=('test',))
  • print('Child process will start.')
  • p.start()
  • p.join() # 等待子進程結束后再繼續往下運行,通常用于進程間的同步。
  • print('Child process end.')
  • # 執行結果
  • Parent process 928.
  • Process will start.
  • Run child process test (929)...
  • Process end.
  • 如果要啟動大量的子進程,可以用進程池(Pool)的方式批量創建子進程。
  • subprocess模塊可以讓我們非常方便的啟動一個子進程,然后控制其輸入和輸出。
  • multiprocessing模塊包裝了底層的機制,提供了queue,pipes等多種方式來交換數據達到進程間的通信
  • 2.2 多線程

    Python標準庫提供了兩個模塊,_thread(低級模塊)和threaing(高級模塊),一般使用threading。

  • import time, threading
  • # 新線程執行的代碼:
  • def loop():
  • print('thread %s is running...' % threading.current_thread().name)
  • n = 0
  • while n < 5:
  • n = n + 1
  • print('thread %s >>> %s' % (threading.current_thread().name, n))
  • time.sleep(1)
  • print('thread %s ended.' % threading.current_thread().name)
  • print('thread %s is running...' % threading.current_thread().name)
  • t = threading.Thread(target=loop, name='LoopThread')
  • t.start()
  • t.join()
  • print('thread %s ended.' % threading.current_thread().name)
  • # 執行結果
  • thread MainThread is running...
  • thread LoopThread is running...
  • thread LoopThread >>> 1
  • thread LoopThread >>> 2
  • thread LoopThread >>> 3
  • thread LoopThread >>> 4
  • thread LoopThread >>> 5
  • thread LoopThread ended.
  • thread MainThread ended.
  • 在多線程中,所有的變量為線程共享,任何一個線程都能修改變量。

  • # 經典存款案例
  • import time, threading
  • # 假定這是你的銀行存款:
  • balance = 0
  • def change_it(n):
  • # 先存后取,結果應該為0:
  • global balance
  • balance = balance + n
  • balance = balance - n
  • def run_thread(n):
  • for i in range(100000):
  • change_it(n)
  • t1 = threading.Thread(target=run_thread, args=(5,))
  • t2 = threading.Thread(target=run_thread, args=(8,))
  • t1.start()
  • t2.start()
  • t1.join()
  • t2.join()
  • print(balance)
  • 當多個線程同時執行的時候,只有一個線程能獲得鎖(Lock),然后繼續執行代碼,其他線程就繼續等待直到獲得鎖為止。
    鎖的好處是確保了某段關鍵代碼只有一個線程從頭到尾完整的執行,壞處就是組織了多線程的運行,由于存在多個鎖,不同的線程持有不同的鎖,并試圖獲取對方持有的鎖,可能會造成死鎖,導致多個線程同時掛起,既不能執行,也不能結束。
    Python解釋器由于設計時有GIL全局鎖,導致多線程無法利用多核。

    2.3 ThreadLocal

    在多線程的環境下,每個線程都有自己的數據,一個線程使用自己的局部變量比使用全局變量好,局部變量只有線程自己能看見,不影響其他線程,而全局變量的修改必須加鎖,局部變量在傳遞起來很麻煩。

  • import threading
  • # 創建全局ThreadLocal對象:
  • local_school = threading.local()
  • def process_student():
  • # 獲取當前線程關聯的student:
  • std = local_school.student
  • print('Hello, %s (in %s)' % (std, threading.current_thread().name))
  • def process_thread(name):
  • # 綁定ThreadLocal的student:
  • local_school.student = name
  • process_student()
  • t1 = threading.Thread(target= process_thread, args=('Alice',), name='Thread-A')
  • t2 = threading.Thread(target= process_thread, args=('Bob',), name='Thread-B')
  • t1.start()
  • t2.start()
  • t1.join()
  • t2.join()
  • # 執行結果
  • Hello, Alice (in Thread-A)
  • Hello, Bob (in Thread-B)
  • ThreadLocal最常用的地方就是為每個線程綁定一個數據庫連接,HTTP請求,用戶身份信息等,這樣一個線程所有調用到的處理函數都可以非常方便的訪問這些資源。

    2.4 進程 vs. 線程

    多進程模式的最大優點就是穩定性高,一個子進程崩潰了,不會影響到主進程和其他子進程,最大的缺點就是創建進程的代價大。
    多線程模式通常會比多進程快一點,最大的缺點就是任何一個線程掛掉都有可能直接造成整個進程崩潰,因為所有線程共享進程的內存。
    多任務一旦到了一個限度(臨界點),就會消耗掉系統所有的資源,結果效率急劇下降,所有任務都做不好。
    任務的類型分為計算密集型和IO密集型

  • 計算密集型任務的特點就是要進行大量的計算,消耗CPU資源,要高效的利用cpu,計算密集型任務同時進行的數量應當等于cpu的核心數。
  • IO密集型,涉及到網絡,磁盤IO的任務都是IO密集型任務,CPU消耗少,任務大部分時間都是在等待IO操作完成,常見的大部分任務都是IO密集型任務。
  • 充分利用操作系統提供的異步IO支持,就可以單進程單線程模型來執行多任務,這種全新的模型稱為事件驅動模型,Nginx就是支持異步IO的服務器。在Python上,單進程的異步編程模型稱為協程。

    2.5 分布式進程

    在多線程和多進程中優先選擇多進程,因為進程更穩定,而且進程可以分布到多臺機器上,而線程只能在同一臺機器上的同一個cpu上。
    Python的multiprocessing模塊不但支持多進程,其中managers子模塊還支持把多進程分布到多臺機器上。一個服務進程可以作為調度者,將任務分布到其他多個子進程中,依靠網絡通信。
    Queue的作用是用來傳遞任務和接收結果,每個任務的描述數量量要盡量小。


    感謝廖雪峰的官方網站提供的教程。Python學習筆記系列都基于廖老師的教程



    來自為知筆記(Wiz)

    轉載于:https://www.cnblogs.com/aniudcs/p/84267852c4fe4782610709d78a1d026c.html

    總結

    以上是生活随笔為你收集整理的Python学习笔记(六)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。