python&&ftp上傳和多線程開發&&學習筆記
- FTP文件上傳
- FTP文件上傳示例
- 堡壘機程序示例
- SSH密碼賬號遠程登錄服務器示例
- SSH密鑰遠程登錄服務器示例
- SSH上傳和下載文件
- 線程與進程簡介
- 應用程序、進程、線程的關系
- 簡單創建線程示例1
- 多線程開發的方法
- 多線程之方法應用示例
- 多線程之自定義線程類示例
- 多線程之生產者與消費者模型示例一
- 函數式編程實現生產者與消費者模型
- 多線程開發之線程鎖
- 多線程開發之event事件
FTP文件上傳
FTP文件上傳示例
#!/usr/bin/env python
#coding:utf-8
#導入模塊socketserver,利用多線程實現多個用戶同時上傳下載文件
import
socketserver
import
os
from
test
.
test_decimal
import
file
class
myServer
(
socketserver
.
BaseRequestHandler
)
:
def
handle
(
self
)
:
#定義文件存放根路徑
basePath
=
'D:/backupAll\eclipseRoot\temp'
clientObj
=
self
.
request
print
(
'連接成功...'
)
while
True
:
#獲取發送頭信息
preData
=
clientObj
.
recv
(
1024
)
preDataToStr
=
str
(
preData
,
encoding
=
"utf8"
)
print
(
preDataToStr
)
cmd
,
fileName
,
fileSize
=
preDataToStr
.
split
(
'|'
)
recvSize
=
0
#拼接路徑
fileDir
=
os
.
path
.
join
(
basePath
,
fileName
)
f
=
file
(
fileDir
,
'wb'
)
Flag
=
True
while
Flag
:
if
int
(
fileSize
)
>
recvSize
:
data
=
clientObj
.
recv
(
1024
)
recvSize
+=
len
(
data
)
else
:
recvSize
=
0
FLag
=
False
#數據由內存寫入硬盤
f
.
write
(
data
)
print
(
'上傳完畢'
)
instance
=
socketserver
.
ThreadingTCPServer
(
(
'127.0.0.1'
,
9999
)
,
myServer
)
instance
.
serve_forever
(
)
client.py
#!/usr/bin/env python
#coding:utf-8
#由于文件的發送傳輸需要經過緩沖區,緩沖區大小固定(一般為8096),所以在實現對文件的發送傳輸時需要將文件切割成固定大小發送。
#導入模塊
from
pip
.
_vendor
.
distlib
.
compat
import
raw_input
from
test
.
test_decimal
import
file
import
socket
import
os
#定義變量
ipAddress
=
(
"127.0.0.1"
,
9999
)
socketObj
=
socket
.
socket
(
)
socketObj
.
connect
(
ipAddress
)
#創造重復循環
while
True
:
#接收"文件操作命令(上傳(put)、下載(get))|文件路徑"
input
=
raw_input
(
'path:'
)
#分離存放文件操作命令(上傳、下載)和文件路徑
cmd
,
path
=
input
.
split
(
'|'
)
#定義文件名稱
fileName
=
os
.
path
.
basename
(
path
)
#定義文件大小
fileSize
=
os
.
stat
(
path
)
.
st_size
strOne
=
cmd
+
"|"
+
fileName
+
"|"
+
str
(
fileSize
)
strToBit
=
strOne
.
encode
(
encoding
=
'utf_8'
,
errors
=
'strict'
)
#發送消息到
socketObj
.
send
(
strToBit
)
#文件發送進度
sendSize
=
0
f
=
file
(
path
,
'rb'
)
Flag
=
True
while
Flag
:
#如果文件發送剩余大小不足1024,則讀取發送剩余大小數據并結束重復循環
if
sendSize
+
1024
>
fileSize
:
data
=
f
.
read
(
fileSize
-
sendSize
)
Flag
=
False
#否則,讀取發送固定大小文件數據并記錄w文件發送進度
else
:
data
=
f
.
read
(
1024
)
sendSize
+=
1024
f
.
close
(
)
socketObj
.
close
(
)
堡壘機程序示例
需求
:記錄用戶在服務器的所有操作
1.需要一臺主機當做堡壘機
2.所有用戶只能登陸堡壘機
3.登陸堡壘機后,可以遠程服務器進行操作
4.記錄用戶的所有操作
過程
:登陸堡壘機》選擇服務器》操作服務器:記錄操作
實現過程
:
1.創建堡壘機用戶
2.用戶登陸堡壘機后
SSH密碼賬號遠程登錄服務器示例
sshDemo.py
#!/usr/bin/env python
#coding:utf-8
#導入模塊
import
paramiko
#實例化
ssh
=
paramiko
.
SSHClient
(
)
#應對第一個遠程登錄的用戶簽名(yes or no),該行代碼默認填寫yes。
ssh
.
set_missing_host_key_policy
(
paramiko
.
AutoAddPolicy
(
)
)
#遠程登錄賬號,密碼
ssh
.
connect
(
'192.168.1.223'
,
22
,
'root'
,
'yibotong'
)
#設置需要使用Linux命令并捕捉命令返回結果(輸入,輸出,錯誤)
stdin
,
stdout
,
stderr
=
ssh
.
exec_command
(
'df'
)
#打印結果
print
(
stdout
.
read
(
)
)
ssh
.
close
(
)
;
SSH密鑰遠程登錄服務器示例
服務器操作生成密鑰操作
#ssh命令產生密鑰對
ssh-keygen -t rsa
#將本地公鑰復制到遠程服務器內部(/root/.ssh/id_rsa.pub)
ssh-copy-id root@192.168.1.139
python密鑰登錄
#!/usr/bin/env python
#coding:utf-8
#導入模塊
import
paramiko
#定義私鑰文件位置
private_key_path
=
'/home/auto/.ssh/id_rsa'
#取出私鑰
key
=
paramiko
.
RSAKey
.
from_private_key_file
(
private_key_path
)
#實例化
ssh
=
paramiko
.
SSHClient
(
)
#應對第一個遠程登錄的用戶簽名(yes or no),該行代碼默認填寫yes。
ssh
.
set_missing_host_key_policy
(
paramiko
.
AutoAddPolicy
(
)
)
#遠程登錄賬號
ssh
.
connect
(
'192.168.1.223'
,
22
,
username
=
'root'
,
pkey
=
key
)
#設置需要使用Linux命令并捕捉命令返回結果(輸入,輸出,錯誤)
stdin
,
stdout
,
stderr
=
ssh
.
exec_command
(
'df'
)
#打印結果
print
(
stdout
.
read
(
)
)
ssh
.
close
(
)
;
rsa公鑰與私鑰的區別
私鑰是自己用的,用于解密;公鑰用于加密。
rsa公鑰與私鑰工作原理
遠程登錄時,客戶端使用tcp協議發送連接請求(欲連接ssh端口),遠程服務器使用公鑰隨機加密一段數據發送到客戶端,客戶端使用本地私鑰解密,解密完成后將數據發送到服務端,服務端對解密數據進行比對,若匹配成功,則公鑰與私鑰配對成功,即遠程登錄成功。
SSH上傳和下載文件
參考:***cnblogs.com/wupeiqi/articles/4356675.html
線程與進程簡介
應用程序、進程、線程的關系
一個應用程序里面可以有多個進程,一個進程里面可以有多個線程。
全局解釋器鎖
在程序運行過程中,同一時間,一個進程里面只能有一個線程通過全局解釋器鎖進入cpu執行。
多進程與多線程的選擇
計算密集型程序需要消耗大量cpu資源,故選擇多進程模式;IO密集型程序選擇多線程模式。
進程的開銷通常比線程昂貴,因為線程自動共享內存地址空間和文件描述符,這意味著,創建進程比創建線程會花費更多。
在執行一些sleep/read/write/recv/send等會導致阻塞的函數時,當前線程會主動放棄GIL,然后調用相應的系統API,完成后再重新申請GIL.因此,GIL也并不是導致python的多線程完全沒用。在一些IO等待的場合,python的多線程還是發揮了作用,當然如果多線程都是用于CPU密集的代碼,那多線程的執行效率明顯會比單線程的低。
線程是共享內存的,線程由進程管理,所有線程共享主線程的內存空間;進程的內存空間是互相獨立,沒有交集的。
簡單創建線程示例1
#!/usr/bin/env python
#coding:utf-8
#導入threading模塊下的Thread類
from
threading
import
Thread
#定義方法
def
funcOne
(
arg
)
:
print
(
arg
)
print
(
'before start thread'
)
#實例化Thread類形成對象,相當于創建了一個線程.
#使用target參數在定義的方法(函數)與線程之間建立聯系
#線程對象 = Thread(target=函數名,args(參數)=(1(僅需一個參數故此處寫一),))
threadOne
=
Thread
(
target
=
funcOne
,
args
=
(
1
,
)
)
#1后面為什么加逗號?因為當遇到字典、列表、元組時,其與方法、函數在調用時操作類似,故容易因為區分錯誤而報錯,后面加逗號,可以說明這是一個序列,以此作為區分。
#在運行對象時,并不一定馬上執行,按系統調度規則被輪訓到時執行
threadOne
.
start
(
)
print
(
'after start thread'
)
多線程開發的方法
threading.Thread模塊
- start
- getName()
- setName():更改線程名稱
- isDaemon()
- setDaemon()
- join(timeout)
- run
線程創建不宜過多也不宜過少,恰當最好。線程過少時,執行效率低;線程過多時會導致上下文切換頻繁,造成大量資源浪費。
多線程之方法應用示例
#!/usr/bin/env python
#coding:utf-8
#導入threading模塊下的Thread類
from
threading
import
Thread
import
time
#定義方法
def
funcOne
(
arg
)
:
print
(
arg
)
def
funcTwo
(
arg
,
v
)
:
for
item
in
range
(
100
)
:
print
(
item
)
time
.
sleep
(
1
)
print
(
'before start thread'
)
#實例化Thread類形成對象,相當于創建了一個線程.
#使用target參數在定義的方法(函數)與線程之間建立聯系
#線程對象 = Thread(target=函數名,args=(參數1,))
threadOne
=
Thread
(
target
=
funcOne
,
args
=
(
'參數1'
,
)
)
threadTwo
=
Thread
(
target
=
funcTwo
,
args
=
(
'參數1'
,
'參數2'
)
)
#1后面為什么加逗號?因為當遇到字典、列表、元組時,其與方法、函數在調用時操作類似,故容易因為區分錯誤而報錯,后面加逗號,可以說明這是一個序列,以此作為區分。
#在程序運行時,當主線程已經執行結束,而子線程執行緩慢仍未結束時,主線程需要等待子線程執行結束才終止程序運行。
#輸出當前daemon狀態,默認False
print
(
threadTwo
.
isDaemon
(
)
)
#設置daemon狀態,此時不再遍歷100之內的數字。
#通過設置daemon狀態,可以讓子線程隨主線程的執行結束而結束,主線程不再等待子線程(threadOne和threadTwo)執行結束。
threadOne
.
setDaemon
(
True
)
threadTwo
.
setDaemon
(
True
)
#在運行對象時,并不一定馬上執行,按系統調度規則被輪訓到時執行
threadOne
.
start
(
)
threadTwo
.
start
(
)
#每個線程被創建時都擁有一個名字,使用'getName'方法輸出線程的名字如下
print
(
threadOne
.
getName
(
)
)
print
(
threadTwo
.
getName
(
)
)
##Thread-1
print
(
'after start thread'
)
多線程之自定義線程類示例
#!/usr/bin/env python
#coding:utf-8
#導入模塊
from
threading
import
Thread
import
time
#自定義一個線程類myThreadClass繼承父類Thread
#實質是在原有Thread類的基礎上增加自己的功能形成自定義的線程類
class
myThreadClass
(
Thread
)
:
#重寫run方法,因為父類Thread擁有run方法,此處為重寫。
def
run
(
self
)
:
time
.
sleep
(
10
)
print
(
'run方法創建了一個線程,我等了10s才現身'
)
try
:
if
self
.
_target
:
self
.
_target
(
*
self
.
_args
,
**
self
.
_kwargs
)
finally
:
# Avoid a refcycle if the thread is running a function with
# an argument that has a member that points to the thread.
del
self
.
_target
,
self
.
_args
,
self
.
_kwargs
def
funcThree
(
)
:
print
(
'funcThree'
)
#執行myThreadClass類從Thread類繼承的構造函數
threadThree
=
myThreadClass
(
target
=
funcThree
)
threadThree
.
start
(
)
print
(
'主線程已經執行完畢'
)
多線程之生產者與消費者模型示例一
producer.py(非正常)
#!/usr/bin/env python
#coding:utf-8
#導入模塊
from
threading
import
Thread
import
time
#導入隊列模塊的隊列類
from
queue
import
Queue
#定義生產者類,向隊列存放數據
class
producer
(
Thread
)
:
#重寫父類的構造函數__init__
def
__init__
(
self
,
name
,
queue
)
:
#name:生產者的名字
#queue:存放數據的容器
self
.
__Name
=
name
self
.
__Queue
=
queue
#或Thread.__init__(self)
super
(
producer
,
self
)
.
__init__
(
)
#重寫父類的run函數
def
run
(
self
)
:
while
True
:
#判斷隊列是否已滿
if
self
.
__Queue
.
full
(
)
:
#滿則等待1秒
time
.
sleep
(
1
)
else
:
#未滿則向隊列加入數據
self
.
__Queue
.
put
(
'someData'
)
print
(
'%s 向隊列中放置了一個數據'
%
(
self
.
__Name
,
)
)
time
.
sleep
(
1
)
Thread
.
run
(
self
)
#定義消費者類 , 從隊列取出數據
class
consumer
(
Thread
)
:
#重寫父類的構造函數__init__
def
__init__
(
self
,
name
,
queue
)
:
#name:生產者的名字
#queue:存放數據的容器
self
.
__Name
=
name
self
.
__Queue
=
queue
Thread
.
__init__
(
self
)
def
run
(
self
)
:
#判斷隊列是否已空
if
self
.
__Queue
.
empty
(
)
:
#空則等待1秒
time
.
sleep
(
1
)
else
:
#未空則從隊列拿出一個數據
self
.
__Queue
.
get
(
)
print
(
'%s 從隊列中取走了一個數據'
%
(
self
.
__Name
,
)
)
time
.
sleep
(
1
)
Thread
.
run
(
self
)
#創建隊列對象并設置隊列最大為10。
#隊列特性:先進先出,線程安全的
queueObj
=
Queue
(
maxsize
=
100
)
#使用xxx對數據結構(序列、列表等)上鎖,同一時間僅允許一個線程對上鎖的數據結構進行操作。
#向隊列存放數據
queueObj
.
put
(
'1'
)
#查看隊列內容
print
(
queueObj
.
queue
)
#使用queueObj.empty()判斷隊列時候為空
print
(
queueObj
.
empty
(
)
)
#從隊列取出數據
print
(
queueObj
.
get
(
)
)
print
(
queueObj
.
queue
)
print
(
queueObj
.
empty
(
)
)
#使用隊列類創建一個倉庫對象queueObjTwo
queueObjTwo
=
Queue
(
maxsize
=
100
)
#使用生產者類創建生產者對象。因為本質上是繼承了線程類Thread,所以可以認為創建的生產者對象就等同于創建的新的線程
#創建三個生產者
producerOne
=
producer
(
'producerYiHao'
,
queueObjTwo
)
producerOne
.
start
(
)
producerTwo
=
producer
(
'producerErHao'
,
queueObjTwo
)
producerTwo
.
start
(
)
producerThree
=
producer
(
'producerSanHao'
,
queueObjTwo
)
producerThree
.
start
(
)
print
(
queueObjTwo
.
queue
)
#使用消費者類創建消費者對象。因為本質上是繼承了線程類Thread,所以可以認為創建的消費者對象就等同于創建的新的線程
#創建二十個消費者
for
item
in
range
(
20
)
:
name
=
'consumer%d'
%
(
item
,
)
name
=
consumer
(
name
,
queueObjTwo
)
name
.
start
(
)
consumerOne
=
consumer
(
'consumerYiHao'
,
queueObjTwo
)
consumerOne
.
start
(
)
print
(
queueObjTwo
.
queue
)
消費者生產者模型優點
解耦:令一個程序的各個部分之間關聯性降到最低。
函數式編程實現生產者與消費者模型
producerDemoTwo.py
#!/usr/bin/env python
#coding:utf-8
import
threading
import
time
import
queue
import
random
def
producer
(
name
,
que
)
:
while
True
:
if
que
.
qsize
(
)
<
3
:
que
.
put
(
'baozi'
)
print
(
'%s make a baozi...'
%
name
)
else
:
print
(
'有三個包子,吃了在做'
)
#隨機等待一到五秒
time
.
sleep
(
random
.
randrange
(
5
)
)
def
consumer
(
name
,
que
)
:
while
True
:
#使用try捕捉錯誤異常,若隊列為空,則打印異常輸出,此時consumer線程不再中斷。沒有捕捉錯誤異常且隊列為空時,consumer線程拋出異常并中斷
try
:
#使用'que.get()'時,若隊列中無數據,則阻塞;使用'que.get_nowait()'時,若隊列中無數據,則拋出異常
que
.
get_nowait
(
)
print
(
'%s eat a baozi'
%
name
)
#隨機等待一到三秒
except
Exception
:
print
(
u
'baozi 吃光了'
)
time
.
sleep
(
random
.
randrange
(
5
)
)
q
=
queue
.
Queue
(
)
p1
=
threading
.
Thread
(
target
=
producer
,
args
=
[
'chef1'
,
q
]
)
p2
=
threading
.
Thread
(
target
=
producer
,
args
=
[
'chef2'
,
q
]
)
p1
.
start
(
)
p2
.
start
(
)
c1
=
threading
.
Thread
(
target
=
consumer
,
args
=
[
'consu1'
,
q
]
)
c2
=
threading
.
Thread
(
target
=
consumer
,
args
=
[
'consu2'
,
q
]
)
c1
.
start
(
)
c2
.
start
(
)
多線程開發之線程鎖
線程鎖中的threading.Lock和threading.Rlock
線程安全:
因為多個線程之間共享一份內存數據,為了防止出現多個線程同時修改一份內存數據的情況,需要使用線程鎖。
定義遞歸鎖對象,可以在鎖內繼續加鎖而不會出現阻塞現象。
lock = threading.RLock()
定義線程鎖對象,同時允許有四個線程對同一份數據進行操作。
lock = threading.BoundedSemaphore(4)
#!/usr/bin/env python
#coding:utf-8
import
threading
import
time
#定義全局變量num,多線程同時啟動時,共享內存數據全局變量num
num
=
0
#定義函數
def
run
(
n
)
:
#聲明變量num為全局變量
time
.
sleep
(
1
)
global
num
#獲取鎖,當前線程獨占對該數據的操作
#鎖的位置應當僅放置于對數據操作的代碼段外面。該代碼段將變成串行線程。
lock
.
acquire
(
)
num
+=
1
print
(
num
)
lock
.
release
(
)
#run('dd')
#定義線程鎖對象
lock
=
threading
.
Lock
(
)
#定義遞歸鎖對象,可以在鎖內繼續加鎖而不會出現阻塞現象。
#lock = threading.RLock()
#定義線程鎖對象,同時允許有四個線程對同一份數據進行操作。
#lock = threading.BoundedSemaphore(4)
#生成十個線程
for
i
in
range
(
100
)
:
t
=
threading
.
Thread
(
target
=
run
,
args
=
(
i
,
)
)
t
.
start
(
)
#此時由于多個線程同時執行函數run修改全局變量num,num的值容易出現異常。
#鎖內加鎖,程序會出現阻塞(死鎖)現象。出現該問題時,使用'lock = threading.RLock()'遞歸鎖可以解決.
多線程開發之event事件
#!/usr/bin/env python
#coding:utf-8
import
threading
import
time
#實現兩個線程之間通過event事件來進行交互。
#定義生產者
def
producer
(
)
:
print
(
u
'等人來買包子'
)
#等待事件,阻塞狀態
event
.
wait
(
)
#使用'isSet'判斷事件狀態(是否為true).此時不存在阻塞狀態
#print(event.isSet())
#清空事件時間狀態
event
.
clear
(
)
print
(
u
'剛剛有個摳腳大漢來買包子了'
)
print
(
u
'dang dang dang ,開工做包子啦'
)
#三秒過后
time
.
sleep
(
10
)
print
(
u
'啦啦啦,包子出鍋啦'
)
event
.
set
(
)
print
(
u
'歪,妖妖靈嗎,包子好了,趁熱買吧'
)
#定義消費者
def
consumer
(
)
:
print
(
u
'俺去買包子'
)
#設置標志,觸發事件
event
.
set
(
)
print
(
u
'(顧客)俺剛剛跟廚師說做倆包子,俺要買'
)
time
.
sleep
(
3
)
while
True
:
if
event
.
isSet
(
)
:
print
(
'看表:時間到了'
)
break
else
:
print
(
'等待中,肚子咕咕叫'
)
time
.
sleep
(
1
)
event
.
wait
(
)
print
(
u
'俺收到通知,:您的包子出鍋啦,趕緊趁熱去買吧'
)
#定義事件觸發,消費者觸發事件去生產者那邊買包子
event
=
threading
.
Event
(
)
p1
=
threading
.
Thread
(
target
=
producer
)
p2
=
threading
.
Thread
(
target
=
consumer
)
p1
.
start
(
)
p2
.
start
(
)
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
