『壹』 如何通過IP訪問並運行伺服器上的python文件
很多種方法,例如:
rpc遠程調用.通過ip地址,遠程指定python文件,直接調用
寫一個簡單的socket,進行通信,發送命令,根據命令啟動python文件
通過http協議,建立簡單的web服務,通過http請求調用
通過消息隊列,例如zmq,rabbitmq,amq,發送消息或者命令,由消費者調用python文件.
『貳』 通信專業的學習python有用么
肯定有用,這個語言很實用,現在互聯網行業這么火爆,你學了python,就多了一個技能傍身,職業選擇也多了一個,憑借python,你可以在很多互聯網企業找到工作。
『叄』 Python網路編程 -- TCP/IP
首先放出一個 TCP/IP 的程序,這里是單線程伺服器與客戶端,在多線程一節會放上多線程的TCP/IP服務程序。
這里將服務端和客戶端放到同一個程序當中,方便對比服務端與客戶端的不同。
TCP/IP是網際網路的通信協議,其參考OSI模型,也採用了分層的方式,對每一層制定了相應的標准。
網際協議(IP)是為全世界通過互聯網連接的計算機賦予統一地址系統的機制,它使得數據包能夠從互聯網的一端發送至另一端,如 130.207.244.244,為了便於記憶,常用主機名代替IP地址,例如 .com。
UDP (User Datagram Protocol,用戶數據報協議) 解決了上述第一個問題,通過埠號來實現了多路復用(用不同的埠區分不同的應用程序)但是使用UDP協議的網路程序需要自己處理丟包、重包和包的亂序問題。
TCP (Transmission Control Protocol,傳輸控制協議) 解決了上述兩個問題,同樣使用埠號實現了復用。
TCP 實現可靠連接的方法:
socket通信模型及 TCP 通信過程如下兩張圖。
[圖片上傳失敗...(image-6d947d-1610703914730)]
[圖片上傳失敗...(image-30b472-1610703914730)]
socket.getaddrinfo(host, port, family, socktype, proto, flags)
返回: [(family, socktype, proto, cannonname, sockaddr), ] 由元組組成的列表。
family:表示socket使用的協議簇, AF_UNIX : 1, AF_INET: 2, AF_INET6 : 10。 0 表示不指定。
socktype: socket 的類型, SOCK_STREAM : 1, SOCK_DGRAM : 2, SOCK_RAW : 3
proto: 協議, 套接字所用的協議,如果不指定, 則為 0。 IPPROTO_TCP : 6, IPPRTOTO_UDP : 17
flags:標記,限制返回內容。 AI_ADDRCONFIG 把計算機無法連接的所有地址都過濾掉(如果一個機構既有IPv4,又有IPv6,而主機只有IPv4,則會把 IPv6過濾掉)
AI _V4MAPPED, 如果本機只有IPv6,服務卻只有IPv4,這個標記會將 IPv4地址重新編碼為可實際使用的IPv6地址。
AI_CANONNAME,返回規范主機名:cannonname。
getaddrinfo(None, 'smtp', 0, socket.SOCK_STREAM, 0, socket.AP_PASSIVE)
getaddrinfo('ftp.kernel.org', 'ftp', 0, 'socket.SOCK_STREAM, 0, socket.AI_ADDRCONFIG | socket.AI_V4MAPPED)
利用已經通信的套接字名提供給getaddrinfo
mysock = server_sock.accept()
addr, port = mysock.getpeername()
getaddrinfo(addr, port, mysock.family, mysock.type, mysock.proto, socket.AI_CANONNAME)
TCP 數據發送模式:
由於 TCP 是發送流式數據,並且會自動分割發送的數據包,而且在 recv 的時候會阻塞進程,直到接收到數據為止,因此會出現死鎖現象,及通信雙方都在等待接收數據導致無法響應,或者都在發送數據導致緩存區溢出。所以就有了封幀(framing)的問題,即如何分割消息,使得接收方能夠識別消息的開始與結束。
關於封幀,需要考慮的問題是, 接收方何時最終停止調用recv才是安全的?整個消息或數據何時才能完整無缺的傳達?何時才能將接收到的消息作為一個整體來解析或處理。
適用UDP的場景:
由於TCP每次連接與斷開都需要有三次握手,若有大量連接,則會產生大量的開銷,在客戶端與伺服器之間不存在長時間連接的情況下,適用UDP更為合適,尤其是客戶端太多的時候。
第二種情況: 當丟包現象發生時,如果應用程序有比簡單地重傳數據聰明得多的方法的話,那麼就不適用TCP了。例如,如果正在進行音頻通話,如果有1s的數據由於丟包而丟失了,那麼只是簡單地不斷重新發送這1s的數據直至其成功傳達是無濟於事的。反之,客戶端應該從傳達的數據包中任意選擇一些組合成一段音頻(為了解決這一問題,一個智能的音頻協議會用前一段音頻的高度壓縮版本作為數據包的開始部分,同樣將其後繼音頻壓縮,作為數據包的結束部分),然後繼續進行後續操作,就好像沒有發生丟包一樣。如果使用TCP,那麼這是不可能的,因為TCP會固執地重傳丟失的信息,即使這些信息早已過時無用也不例外。UDP數據報通常是互聯網實時多媒體流的基礎。
參考資料:
『肆』 用python 怎麼和硬體進行鏈接,通信,交互
本文介紹了用python與文件進行交互的方法,分享給大家,具體如下:
一.文件處理
1.介紹
計算機系統:計算機硬體,操作系統,應用程序
應用程序無法直接操作硬體,通過操作系統來操作文件,進而讀/寫硬體中的文件。
python打開文件過程:
#打開
f=open('a.txt','r')
#通過句柄對文件進行操作
read_f=f.read()
#關閉文件
f.close()
with open('a.txt','r') as f: #不需要關閉
f.close() #回收操作系統打開的文件
del f #回收應用程序級的變數
2.打開文件的模式
a.打開文本文件
#r,只讀模式【默認模式,文件必須存在,不存在則拋出異常】
f=open('a.txt',encoding='utf-8')
data1=f.read()
print(f.readline(),end='')
print(f.readlines())
#w,只寫模式【不可讀;不存在則創建;存在則清空內容】
f=open('a.txt','w',encoding='utf-8')
f.write('werf')
#a,只追加寫模式【不可讀;不存在則創建;存在則只追加內容】
f=open('a.txt','a',encoding='utf-8')
f.write('werf\n')
b.對於非文本文件,只能使用b模式,"b"表示以位元組的方式操作(而所有文件也都是以位元組的形式存儲的,使用這種模式無需考慮文本文件的字元編碼、圖片文件的jgp格式、視頻文件的avi格式
with open('1.jpg','rb') as f_read:
data=f_read.read()
print(data)
with open('a.txt','rb') as f_read:
data=f_read.read().decode('utf-8') #解碼
print(data)
with open('a.txt','wb')as f_write:
f_write.write('adsf'.encode('utf-8'))
'''
練習,利用b模式,編寫一個cp工具,要求如下:
1. 既可以拷貝文本又可以拷貝視頻,圖片等文件
2. 用戶一旦參數錯誤,列印命令的正確使用方法,如usage: cp source_file target_file
'''
import sys
if len(sys.argv)!=3:
print('usage:cp source_file target_file')
sys.exit()
source_file,target_file=sys.argv[1],sys.argv[2]
print()
with open(source_file,'rb')as f_read,open(target_file,'wb')as f_write:
for line in f_read:
f_write.write(line)
3.文件內游標的移動
#以文本模式讀文件,n代表的是字元的個數
with open('a.txt','r')as f_read:
data=f_read.read(6)
print(data)
#以b模式讀文件,n代表的是位元組的個數
with open('a.txt','rb')as f_read:
data=f_read.read(6)
print(data)
# tell:告訴當前游標的位置
with open('a.txt','r',encoding='utf-8')as f_read:
data=f_read.read(4)
data1=f_read.tell()
print(data,data1)
# seek:移動游標(0:文件開頭默認;1:文件當前游標;2:文件末尾)
with open('a.txt', 'r', encoding='utf-8')as f_read:
data = f_read.seek(3)
data1 = f_read.read()
print(data, data1)
# 實現tail功能
import time
with open('access.log', 'rb')as f_read:
f_read.seek(0,2)
while True:
line = f_read.readline()
if line:
print(line.decode('utf-8'),end='')
else:
time.sleep(1)
4.文件的修改
import os
with open('a.txt') as read_f,open('.a.txt.swap','w') as write_f:
for line in read_f:
line=line.replace('alex','SB')
write_f.write(line)
os.remove('a.txt')
os.rename('.a.txt.swap','a.txt')
『伍』 python基礎(21)-線程通信
到這里,我們要聊一下線程通信的內容;
首先,我們拋開語言不談,先看看比較基礎的東西,線程間通信的方式;其實也就是哪幾種(我這里說的,是我的所謂的知道的。。。)事件,消息隊列,信號量,條件變數(鎖算不算?我只是認為是同步的一種);所以我們也就是要把這些掌握了,因為各有各的好處嘛;
條件變數我放到了上面的線程同步裡面講了,我總感覺這算是同步的一種,沒有很多具體信息的溝通;同時吧,我認為條件變數比較重要,因為這種可以應用於線程池的操作上;所以比較重要;這里,拋開條件變數不談,我們看看其他的東西;
1、消息隊列:
queue 模塊下提供了幾個阻塞隊列,這些隊列主要用於實現線程通信。在 queue 模塊下主要提供了三個類,分別代表三種隊列,它們的主要區別就在於進隊列、出隊列的不同。
關於這三個隊列類的簡單介紹如下:
queue.Queue(maxsize=0):代表 FIFO(先進先出)的常規隊列,maxsize 可以限制隊列的大小。如果隊列的大小達到隊列的上限,就會加鎖,再次加入元素時就會被阻塞,直到隊列中的元素被消費。如果將 maxsize 設置為 0 或負數,則該隊列的大小就是無限制的。
queue.LifoQueue(maxsize=0):代表 LIFO(後進先出)的隊列,與 Queue 的區別就是出隊列的順序不同。
PriorityQueue(maxsize=0):代表優先順序隊列,優先順序最小的元素先出隊列。
這三個隊列類的屬性和方法基本相同, 它們都提供了如下屬性和方法:
Queue.qsize():返回隊列的實際大小,也就是該隊列中包含幾個元素。
Queue.empty():判斷隊列是否為空。
Queue.full():判斷隊列是否已滿。
Queue.put(item, block=True, timeout=None):向隊列中放入元素。如果隊列己滿,且 block 參數為 True(阻塞),當前線程被阻塞,timeout 指定阻塞時間,如果將 timeout 設置為 None,則代表一直阻塞,直到該隊列的元素被消費;如果隊列己滿,且 block 參數為 False(不阻塞),則直接引發 queue.FULL 異常。
Queue.put_nowait(item):向隊列中放入元素,不阻塞。相當於在上一個方法中將 block 參數設置為 False。
Queue.get(item, block=True, timeout=None):從隊列中取出元素(消費元素)。如果隊列已滿,且 block 參數為 True(阻塞),當前線程被阻塞,timeout 指定阻塞時間,如果將 timeout 設置為 None,則代表一直阻塞,直到有元素被放入隊列中; 如果隊列己空,且 block 參數為 False(不阻塞),則直接引發 queue.EMPTY 異常。
Queue.get_nowait(item):從隊列中取出元素,不阻塞。相當於在上一個方法中將 block 參數設置為 False。
其實我們想想,這個隊列,是python進行封裝的,那麼我們可以用在線程間的通信;同時也是可以用做一個數據結構;先進先出就是隊列,後進先出就是棧;我們用這個棧寫個十進制轉二進制的例子:
沒毛病,可以正常的列印;其中需要注意的就是,maxsize在初始化的時候如果是0或者是個負數的話,那麼就會是不限制大小;
那麼其實我們想想,我們如果用做線程通信的話,我們兩個線程,可以把隊列設置為1的大小,如果是1對多,比如是創建者和消費者的關系,我們完全可以作為消息隊列,比如說創建者一直在創建一些東西,然後放入到消息隊列裡面,然後供消費著使用;就是一個很好的例子;所以,其實說是消息隊列,也就是隊列,沒差;
=====================================================================
下面來看一下事件
Event 是一種非常簡單的線程通信機制,一個線程發出一個 Event,另一個線程可通過該 Event 被觸發。
Event 本身管理一個內部旗標,程序可以通過 Event 的 set() 方法將該旗標設置為 True,也可以調用 clear() 方法將該旗標設置為 False。程序可以調用 wait() 方法來阻塞當前線程,直到 Event 的內部旗標被設置為 True。
Event 提供了如下方法:
is_set():該方法返回 Event 的內部旗標是否為True。
set():該方法將會把 Event 的內部旗標設置為 True,並喚醒所有處於等待狀態的線程。
clear():該方法將 Event 的內部旗標設置為 False,通常接下來會調用 wait() 方法來阻塞當前線程。
wait(timeout=None):該方法會阻塞當前線程。
這里我想解釋一下;其實對於事件來說,事件可以看成和條件變數是一樣的,只是我們說說不一樣的地方;
1、對於事件來說,一旦觸發了事件,也就是說,一旦set為true了,那麼就會一直為true,需要clear調內部的標志,才能繼續wait;但是conditon不是,他是一次性的喚醒其他線程;
2、conditon自己帶鎖;事件呢?不是的;沒有自己的鎖;比如說有一個存錢的線程,有一個是取錢的線程;那麼存錢的線程要存錢;需要怎麼辦呢?1、發現銀行沒有錢了(is_set判斷);2、鎖住銀行;3、存錢;4、釋放銀行;5、喚醒事件;對於取錢的人;1、判斷是否有錢;2、被喚醒了,然後鎖住銀行;3、開始取錢;4、清理告訴存錢的人,我沒錢了(clear);5、釋放鎖;6、等著錢存進去;
其實說白了,就是記住一點;這個旗標需要自己clear就對了
寫個例子,怕以後忘了怎麼用;
其實時間和信號量比較像;但是信號量不用自己清除標志位;但是事件是需要的;