python基礎-Process建立程序、join方法、實現ftp多程序
程序概念
程序即正在執行的一個過程或者說一個任務。程序是對正在執行程式的一個抽象,而負責執行任務則是cpu
程式僅僅只是一堆程式碼而已,而程序指的是程式的執行過程。
程序的概念起源於作業系統,程序的建立,排程管理都歸作業系統管
一 作業系統的作用:
1:隱藏醜陋複雜的硬體介面,提供良好的抽象介面
2:管理、排程程序,並且將多個程序對硬體的競爭變得有序
二 多道技術:
1.產生背景:針對單核,實現併發
ps:
現在的主機一般是多核,那麼每個核都會利用多道技術
有4個cpu,運行於cpu1的某個程式遇到io阻塞,會等到io結束再重新排程,會被排程到4個
cpu中的任意一個,具體由作業系統排程演算法決定。
2.空間上的複用:如記憶體中同時有多道程式
3.時間上的複用:複用一個cpu的時間片
強調:遇到io切,佔用cpu時間過長也切,核心在於切之前將程序的狀態儲存下來,這樣
才能保證下次切換回來時,能基於上次切走的位置繼續執行
獲取程序id
getpid是獲得當前程序的程序號
getppid是獲得當前程序的父程序的程序號
import time,os
print(os.getpid(),os.getppid())
time.sleep(1000)
輸出如下:
1512 12032
並行、併發概念
一 併發:單個cpu+多道技術就可以實現併發,(並行也屬於併發)
二 並行:同時執行,只有具備多個cpu才能實現並行
有四個核,六個任務,這樣同一時間有四個任務被執行,假設分別被分配給了cpu1,cpu2,cpu3,cpu4,一旦任務1遇到I/O就被迫中斷執行,此時任務5就拿到cpu1的時間片去執行,而一旦任務1的I/O結束了,作業系統會重新呼叫它(需知程序的排程、分配給哪個cpu執行,由作業系統說了算),可能被分配給四個cpu中的任意一個去執行
Process類的介紹
p.start() #只是在給作業系統發了一個訊號,讓作業系統去開程序(申請記憶體+拷貝父程序的地址空間)
方式一:
from multiprocessing import Process
import time
def task(name):
print('%s is running' %name)
time.sleep(2)
if __name__ == '__main__': #在windows系統下,開子程序的程式碼必須寫到這一行下面
p=Process(target=task,args=('safly1',))
p.start() #只是在給作業系統發了一個訊號,讓作業系統去開程序(申請記憶體+拷貝父程序的地址空間)
p1 = Process(target=task, kwargs={"name":"safly2"})
p1.start()
print('主')
輸出如下:
主
safly1 is running
safly2 is running
方式二:
from multiprocessing import Process
import time
class Myprocess(Process):
def __init__(self,name):
super().__init__()
self.name=name
def run(self):
time.sleep(3)
print('%s is running' % self.name)
if __name__ == '__main__': # 在windows系統下,開子程序的程式碼必須寫到這一行下面
p = Myprocess('safly')
p.start() # p.run()
print('主')
輸出如下:
主
safly is running
Process類的其他方法
from multiprocessing import Process
import time, random
def task():
print('孫子運行了')
time.sleep(3)
def piao(name):
print('%s is piaoing' % name)
time.sleep(random.randint(1, 3))
print('%s is done' % name)
p=Process(target=task,)
p.start()
if __name__ == '__main__':
p1=Process(target=piao,args=('alex',),name='xxxxxxxx')
p1.start()
print(p1.name)
print(p1.pid)
print(p1.is_alive())
print('主')
輸出如下:
E:\python\python_sdk\python.exe E:/python/py_pro/3_Process物件的屬性與方法.py
xxxxxxxx
11816
True
主
alex is piaoing
alex is done
孫子運行了
Process finished with exit code 0
join方法
join:主程序等,等待子程序結束
from multiprocessing import Process
import time,random
def piao(name):
print('%s is piaoing' %name)
time.sleep(random.randint(1,3))
print('%s is done' %name)
if __name__ == '__main__':
p1=Process(target=piao,args=('alex',))
p2=Process(target=piao,args=('wxx',))
p3=Process(target=piao,args=('yxx',))
p1.start()
p2.start()
p3.start()
p3.join() # join(p)
p1.join() #join(p)
p2.join() #join(p)
print('主')
輸出如下:
alex is piaoing
wxx is piaoing
yxx is piaoing
alex is done
wxx is done
yxx is done
主
程序只要start就會在開始運行了,所以p1-p3.start()時,系統中已經有3個併發的程序了
而我們p1.join()是在等p1結束,沒錯p1只要不結束主執行緒就會一直卡在原地,這也是問題的關鍵
join是讓主執行緒等,而p1-p3仍然是併發執行的,p1.join的時候,其餘p2,p3仍然在執行,等#p1.join結束,可能p2,p3早已經結束了,這樣p2.join,p3.join直接通過檢測,無需等待
所以3個join花費的總時間仍然是耗費時間最長的那個程序執行的時間
上述例子可以簡寫成如下:
from multiprocessing import Process
import time,random
def piao(name):
print('%s is piaoing' %name)
time.sleep(random.randint(1,3))
print('%s is done' %name)
if __name__ == '__main__':
p1=Process(target=piao,args=('alex',))
p2=Process(target=piao,args=('wxx',))
p3=Process(target=piao,args=('yxx',))
p_l=[p1,p2,p3]
for p in p_l:
p.start()
for p in p_l:
p.join()
print('主')
利用多程序實現ftp套接字
我們之前寫過非多程序的tcp套接字通訊,這裡在貼出程式碼來看下
server
import socket
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(("127.0.0.1",8081))
server.listen(5)
while True:
conn,addr = server.accept()
while True:
data = conn.recv(1024)
if not data:break
dataStr = data.decode("utf-8")
print(dataStr)
conn.send(dataStr.upper().encode("utf-8"))
conn.close()
server.close()
client
import socket
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(("127.0.0.1",8081))
while True:
msg = input("請輸入:")
if not msg:continue
client.send(msg.encode("utf-8"))
data = client.recv(1024)
print(data.decode("utf-8"))
client.close()
我們要為server端新增多程序(client不做修改)
import socket
from multiprocessing import Process
def task(conn,addr):
while True:
try:
msg = conn.recv(1024)
if not msg:break
conn.send(msg.upper())
except ConnectionResetError:
break
if __name__ == "__main__":
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(("127.0.0.1", 6087))
server.listen(5)
while True:
conn, addr = server.accept()
p = Process(target=task,args=(conn,addr))
p.start()