一、paramiko

二、进程、与线程区别

三、python GIL全局解释器锁

四、线程

    1. 语法
    2. join
    3. 线程锁之Lock\Rlock\信号量
    4. 将线程变为守护进程
    5. Event事件 
    6. queue队列
    7. 生产者消费者模型

  一、paramiko

  用于远程连接并执行简单的命令

  使用用户名密码连接:

 import paramiko

 # 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='172.16.5.163', port=22, username='root', password='') # 执行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 获取命令结果
result = stdout.read()
print(result.decode()) # 关闭连接
ssh.close() 结果
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/mapper/VolGroup-lv_root 51606140 1518048 47466652 4% /
tmpfs 510172 0 510172 0% /dev/shm
/dev/sda1 495844 33461 436783 8% /boot
/dev/mapper/VolGroup-lv_home 2059640248 203016 1954813516 1% /home

  使用公钥连接

import paramiko

private_key = paramiko.RSAKey.from_private_key_file('id_rsa.txt')

#创建SSH对象
ssh = paramiko.SSHClient()
#允许连接不在know_host文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #连接服务器
ssh.connect(hostname='172.16.5.163',port=22,username='root',pkey=private_key) #执行命令
stdin,stdout,stderr = ssh.exec_command('df -h') #获取命令结果
restult = stdout.read() #打印执行结果
print(restult.decode()) #关闭连接
ssh.close()

  SFTPClient使用用户名密码完成上传下载

 import paramiko

 transport = paramiko.Transport(('172.16.5.163',22))
transport.connect(username='root',password='') sftp = paramiko.SFTPClient.from_transport(transport)
# 将location.py 上传至服务器 /tmp/test.py
sftp.put('D:\\test1\\put.txt', '/tmp/put.txt')
# 将remove_path 下载到本地 local_path
sftp.get('/tmp/get.txt', 'D:\\test1\\get.txt') transport.close()

  SFTPClient使用公钥完成上传下载

 import paramiko

 private_key = paramiko.RSAKey.from_private_key_file('id_rsa.txt')

 transport = paramiko.Transport(('172.16.5.163', 22))
transport.connect(username='root', pkey=private_key ) sftp = paramiko.SFTPClient.from_transport(transport)
# 将location.py 上传至服务器 /tmp/test.py
sftp.put('D:\\test1\\put.txt', '/tmp/put.txt')
# 将remove_path 下载到本地 local_path
sftp.get('/tmp/get.txt', 'D:\\test1\\get.txt') transport.close()

  

  二、进程、与线程区别

  线程:是操作系统的最小调度单元,一堆指令的集合。

  进程:操作CPU,必须先创建一个线程

进程和线程的区别

启动一个线程比启动一个进程快,运行速度没有可比性。
先有一个进程然后才能有线程。
1、进程包含线程
2、线程共享内存空间
3、进程内存是独立的(不可互相访问)
4、进程可以生成子进程,子进程之间互相不能互相访问(相当于在父级进程克隆两个子进程)
5、在一个进程里面线程之间可以交流。两个进程想通信,必须通过一个中间代理来实现
6、创建新线程很简单,创建新进程需要对其父进程进行克隆。
7、一个线程可以控制或操作同一个进程里面的其它线程。但进程只能操作子进程。
8、父进程可以修改不影响子进程,但不能修改。

  三、python GIL全局解释器锁

In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.)

上面的核心意思就是,无论你启多少个线程,你有多少个cpu, Python在执行的时候会淡定的在同一时刻只允许一个线程运行,擦。。。,那这还叫什么多线程呀?莫如此早的下结结论,听我现场讲。

首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念。就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代码。有名的编译器例如GCC,INTEL C++,Visual C++等。Python也一样,同样一段代码可以通过CPython,PyPy,Psyco等不同的Python执行环境来执行。像其中的JPython就没有GIL。然而因为CPython是大部分环境下默认的Python执行环境。所以在很多人的概念里CPython就是Python,也就想当然的把GIL归结为Python语言的缺陷。所以这里要先明确一点:GIL并不是Python的特性,Python完全可以不依赖于GIL

详细说明:http://www.dabeaz.com/python/UnderstandingGIL.pdf

  其实就是为了解决同一时间内多个线程处理一个运算(浪费资源),全局解释器锁解决同一时间如果有线程执行过了,其它线程就不重复运算。

  四、线程

  

  1. 语法

写法一:

 import  threading

 #创建一个函数,每个线程要使用的函数
def fun(n):
print(n) n1 = threading.Thread(target=fun,args=('n1',))#生成一个线程
n2 = threading.Thread(target=fun,args=('n2',))#再生成一个线程 n1.start()#启动n1这个线程
n2.start()#启动n2这个线程 print(n1.getName())#获取线程名
print(n2.getName())#获取线程名

写法二:

import  threading,time

class mythread(threading.Thread):#继承thread.Thread这个函数
def __init__(self,n):
super(mythread,self).__init__()
self.n = n def run(self):#这里这个方法名必须命名为run,否则失败
print('运行线程',self.n) n1 = mythread("n1")
n2 = mythread("n2") n1.start()
n2.start()

   2、join

  用法例如线程n1和n2,想要等n1的结果在执行n2,就需要n1.join。具体如下


 import  threading,time

 class mythread(threading.Thread):#继承thread.Thread这个函数
def __init__(self,n,sleep_time):
super(mythread,self).__init__()
self.n = n
self.sleep_time = sleep_time def run(self):#这里这个方法名必须命名为run,否则失败
print("开始运行线程",self.n)
time.sleep(self.sleep_time)#执行完一个线程后停止2秒
print('运行线程结束',self.n,threading.current_thread()) n1 = mythread("n1",2)
n2 = mythread("n2",4) n1.start()
n2.start()
n1.join
print('这里是主程序',threading.current_thread())

 开始运行线程 n1
开始运行线程 n2
这里是主程序 <_MainThread(MainThread, started 12624)>#一个进程启动收首先会打印主线程
运行线程结束 n1 <mythread(Thread-1, started 4020)>#这里是普通线程
运行线程结束 n2 <mythread(Thread-2, started 9088)>#这里是普通线程
 

  3、线程锁之Lock\Rlock\信号量

  线程锁:保证同一时间内只有一个线程可以修改一个数据(避免同一时间内多个线程修改同一个数据)

  4、将线程变为守护进程

 import threading
import time def run(n):
print("task",n)
time.sleep(2)
print('停') start_time = time.time()
t_obj = []
for i in range(50):
t = threading.Thread(target=run,args=("t--%s"%i,))
t.setDaemon(True)#把当前线程线程设置为守护进程,必须要写在start前面,否则报错
t.start()
t_obj.append(t) print("主线程执行")#主线程
print("cost:",time.time() - start_time) #非守护进程退出了,就全部退出(这里是主线程执行完毕后,就不等子线程了,主线程退出了,就都退出了)

  线程锁(互斥锁Mutex)

  一个进程下可以启动多个线程,多个线程共享父进程的内存空间,也就意味着每个线程可以访问同一份数据,此时,如果2个线程同时要修改同一份数据,会出现什么状况?

 import time
import threading def addNum():
global num #在每个线程中都获取这个全局变量
print('--get num:',num )
time.sleep(1)
num -=1 #对此公共变量进行-1操作 num = 100 #设定一个共享变量
thread_list = []
for i in range(100):
t = threading.Thread(target=addNum)
t.start()
thread_list.append(t) for t in thread_list: #等待所有线程执行完毕
t.join() print('final num:', num )

正常来讲,这个num结果应该是0, 但在python 2.7上多运行几次,会发现,最后打印出来的num结果不总是0,为什么每次运行的结果不一样呢? 哈,很简单,假设你有A,B两个线程,此时都 要对num 进行减1操作, 由于2个线程是并发同时运行的,所以2个线程很有可能同时拿走了num=100这个初始变量交给cpu去运算,当A线程去处完的结果是99,但此时B线程运算完的结果也是99,两个线程同时CPU运算的结果再赋值给num变量后,结果就都是99。那怎么办呢? 很简单,每个线程在要修改公共数据时,为了避免自己在还没改完的时候别人也来修改此数据,可以给这个数据加一把锁, 这样其它线程想修改此数据时就必须等待你修改完毕并把锁释放掉后才能再访问此数据。

*注:不要在3.x上运行,不知为什么,3.x上的结果总是正确的,可能是自动加了锁

  加锁版本

import time
import threading def addNum():
global num #在每个线程中都获取这个全局变量
print('--get num:',num )
time.sleep(1)
lock.acquire() #修改数据前加锁
num -=1 #对此公共变量进行-1操作
lock.release() #修改后释放 num = 100 #设定一个共享变量
thread_list = []
lock = threading.Lock() #生成全局锁
for i in range(100):
t = threading.Thread(target=addNum)
t.start()
thread_list.append(t) for t in thread_list: #等待所有线程执行完毕
t.join() print('final num:', num )

  

  GIL VS Lock 

  机智的同学可能会问到这个问题,就是既然你之前说过了,Python已经有一个GIL来保证同一时间只能有一个线程来执行了,为什么这里还需要lock? 注意啦,这里的lock是用户级的lock,跟那个GIL没关系 ,具体我们通过下图来看一下+配合我现场讲给大家,就明白了。

  RLock(递归锁)

  一把大锁中还有很多小锁

  

 import threading,time

 def run1():
print("grab the first part data")
lock.acquire()
global num
num +=1
lock.release()
return num
def run2():
print("grab the second part data")
lock.acquire()
global num2
num2+=1
lock.release()
return num2
def run3():
lock.acquire()
res = run1()
print('--------between run1 and run2-----')
res2 = run2()
lock.release()
print(res,res2) if __name__ == '__main__': num,num2 = 0,0
lock = threading.RLock()
for i in range(10):
t = threading.Thread(target=run3)
t.start() while threading.active_count() != 1:
print(threading.active_count())
else:
print('----all threads done---')
print(num,num2)

  信号量:同一时间内,最大允许多个线程运行

 import threading,time

 def run(n):
semaphore.acquire()
time.sleep(1)
print("run the thread: %s\n" %n)
semaphore.release() semaphore = threading.BoundedSemaphore(5) #最多允许5个线程同时运行
for i in range(19):
t = threading.Thread(target=run,args=(i,))
t.start() while threading.active_count() != 1:
pass #print threading.active_count()
else:
print('----all threads done---')

  5、Event事件 

  通过Event来实现两个或多个线程间的交互,下面是一个红绿灯的例子,即起动一个线程做交通指挥灯,生成几个线程做车辆,车辆行驶按红灯停,绿灯行的规则。

  

#event.wait()等待
#event.clear() #把标志位清空
#event.is_set()设定标志位
 import threading,time
event = threading.Event() def lighter():
count = 0
event.set() #先设定绿灯
while True:
if count >5 and count < 10:#改为红灯
event.clear() #把标志位清空
print("\033[41;1m \033[0m")
elif count > 10:
event.set() #变绿灯
count = 0
else:
print("\033[42;1m \033[0m")
time.sleep(1)
count += 1
def car(name):
while True:
if event.is_set():#代表绿灯
print("[%s] running"%name)
time.sleep(1)
else:
print("[%s] 红灯稍等"%name)
event.wait()
print("033[34;1m[%s] green light is on,start going...\033[0m"%name)
lighter = threading.Thread(target=lighter,)
lighter.start()
car1 = threading.Thread(target=car,args=("Tesla",))
car1.start()

  6、queue队列

  提高运行效率,完成程序的解耦。

 >>> import queue
>>> q = queue.Queue()#生成实例
>>> q.put('d1')#存第一个硬盘
>>> q.put('d2')#存第二个硬盘
>>> q.put('d3')#存第三个硬盘
>>> q.qsize()#获取队列大小
3
>>> q.get()#取值(先存先取,没有就卡住),可以通过异常,来获取
'd1'
>>>
>>> q.get()
'd2'
>>> q.get()

queue is especially useful in threaded programming when information must be exchanged safely between multiple threads.

class queue.Queue(maxsize=0) #先入先出
class queue.LifoQueue(maxsize=0) #last in fisrt out 
class queue.PriorityQueue(maxsize=0) #存储数据时可设置优先级的队列

Constructor for a priority queue. maxsize is an integer that sets the upperbound limit on the number of items that can be placed in the queue. Insertion will block once this size has been reached, until queue items are consumed. If maxsize is less than or equal to zero, the queue size is infinite.

The lowest valued entries are retrieved first (the lowest valued entry is the one returned by sorted(list(entries))[0]). A typical pattern for entries is a tuple in the form: (priority_number, data).

exception queue.Empty

Exception raised when non-blocking get() (or get_nowait()) is called on a Queue object which is empty.

exception queue.Full

Exception raised when non-blocking put() (or put_nowait()) is called on a Queue object which is full.

Queue.qsize()
Queue.empty() #return True if empty  
Queue.full() # return True if full 
Queue.put(itemblock=Truetimeout=None)

Put item into the queue. If optional args block is true and timeout is None (the default), block if necessary until a free slot is available. If timeout is a positive number, it blocks at most timeout seconds and raises the Full exception if no free slot was available within that time. Otherwise (block is false), put an item on the queue if a free slot is immediately available, else raise the Full exception (timeout is ignored in that case).

Queue.put_nowait(item)

Equivalent to put(item, False).

Queue.get(block=Truetimeout=None)

Remove and return an item from the queue. If optional args block is true and timeout is None (the default), block if necessary until an item is available. If timeout is a positive number, it blocks at most timeout seconds and raises the Empty exception if no item was available within that time. Otherwise (block is false), return an item if one is immediately available, else raise the Empty exception (timeout is ignored in that case).

Queue.get_nowait()

Equivalent to get(False).

Two methods are offered to support tracking whether enqueued tasks have been fully processed by daemon consumer threads.

Queue.task_done()

Indicate that a formerly enqueued task is complete. Used by queue consumer threads. For each get() used to fetch a task, a subsequent call to task_done() tells the queue that the processing on the task is complete.

If a join() is currently blocking, it will resume when all items have been processed (meaning that a task_done() call was received for every item that had been put() into the queue).

Raises a ValueError if called more times than there were items placed in the queue.

Queue.join() block直到queue被消费完毕

  7、生产者消费者模型

在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。

为什么要使用生产者和消费者模式

在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。

什么是生产者消费者模式

生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。

 import threading,time

 import queue

 q = queue.Queue(maxsize=10)

 def Producer(name):
count = 1
while True:
q.put("骨头%s" % count)
print("生产了骨头",count)
count +=1
time.sleep(0.1) def Consumer(name):
#while q.qsize()>0:
while True:
print("[%s] 取到[%s] 并且吃了它..." %(name, q.get()))
time.sleep(1) p = threading.Thread(target=Producer,args=("Alex",))
c = threading.Thread(target=Consumer,args=("ChengRonghua",))
c1 = threading.Thread(target=Consumer,args=("王森",)) p.start()
c.start()
c1.start()

Python之路-python(paramiko,进程和线程的区别,GIL全局解释器锁,线程)的更多相关文章

  1. python GIL全局解释器锁,多线程多进程效率比较,进程池,协程,TCP服务端实现协程

    GIL全局解释器锁 ''' python解释器: - Cpython C语言 - Jpython java ... 1.GIL: 全局解释器锁 - 翻译: 在同一个进程下开启的多线程,同一时刻只能有一 ...

  2. 【转】进程、线程、 GIL全局解释器锁知识点整理

    转自:https://www.cnblogs.com/alex3714/articles/5230609.html 本节内容 操作系统发展史介绍 进程.与线程区别 python GIL全局解释器锁 线 ...

  3. Python自动化 【第九篇】:Python基础-线程、进程及python GIL全局解释器锁

    本节内容: 进程与线程区别 线程 a)  语法 b)  join c)  线程锁之Lock\Rlock\信号量 d)  将线程变为守护进程 e)  Event事件 f)   queue队列 g)  生 ...

  4. python 之 并发编程(守护线程与守护进程的区别、线程互斥锁、死锁现象与递归锁、信号量、GIL全局解释器锁)

    9.94 守护线程与守护进程的区别 1.对主进程来说,运行完毕指的是主进程代码运行完毕2.对主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕​详细解释:1.主 ...

  5. GIL全局解释器锁、死锁现象、python多线程的用处、进程池与线程池理论

    昨日内容回顾 僵尸进程与孤儿进程 # 僵尸进程: 所有的进程在运行结束之后并不会立刻销毁(父进程需要获取该进程的资源) # 孤儿进程: 子进程正常运行 但是产生该子进程的父进程意外死亡 # 守护进程: ...

  6. python并发编程-多线程实现服务端并发-GIL全局解释器锁-验证python多线程是否有用-死锁-递归锁-信号量-Event事件-线程结合队列-03

    目录 结合多线程实现服务端并发(不用socketserver模块) 服务端代码 客户端代码 CIL全局解释器锁****** 可能被问到的两个判断 与普通互斥锁的区别 验证python的多线程是否有用需 ...

  7. 进程、线程与GIL全局解释器锁详解

    进程与线程的关系: . 线程是最小的调度单位 . 进程是最小的管理单元 . 一个进程必须至少一个线程 . 没有线程,进程也就不复存在 线程特点: 线程的并发是利用cpu上下文的切换(是并发,不是并行) ...

  8. [Python 多线程] GIL全局解释器锁 (十三)

    Queue 标准库queue模块,提供FIFO(先进先出)的Queue.LIFO(后进先出)的队列.优先队列. Queue类是线程安全的,适用于多线程间安全的交换数据.内部使用了Lock和Condit ...

  9. Python 36 GIL全局解释器锁 、vs自定义互斥锁

    一:GIL全局解释器锁介绍 在CPython中,全局解释器锁(或GIL)是一个互斥锁, 它阻止多个本机线程同时执行Python字节码.译文:之所以需要这个锁, 主要是因为CPython的内存管理不是线 ...

随机推荐

  1. UVa 11082 & 最大流的行列模型

    题意: 给出一个矩阵前i行的和与前j列的和,(i∈[1,r],j属于[1,c]),每个元素ai,j∈[1,20],请你还原出这个矩阵,保证有解. SOL: 给网络流建模跪了,神一样的建图,如果我我会怎 ...

  2. 来自于2016.2.23的flag

    正是中午,百废待兴,写点什么调节一会儿心情吧.正巧有许多的想法. 机房来了许多小朋友,多么像一年之前的我啊,想写题,心又纷乱,但不同的是他们比我强太多了. 停课是什么感觉?停课在机房与寒暑假.双休日在 ...

  3. 20145304 Java第六周学习报告

    20145304<Java程序设计>第六周学习总结 教材学习内容总结 1.InputStream与OutputStream: 在Java中,输入串流的代表对象为java.io.InputS ...

  4. Leetcode SortList

    Sort a linked list in O(n log n) time using constant space complexity. 本题利用归并排序即可 归并排序的核心是将两部分合成一部分, ...

  5. ACM 括号配对问题

    括号配对问题 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 现在,有一行括号序列,请你检查这行括号是否配对.   输入 第一行输入一个数N(0<N<=1 ...

  6. 2076. The Drunk Jailer

    Problem A certain prison contains a long hall of n cells, each right next to each other. Each cell h ...

  7. 【HDU】4405 Aeroplane chess

    http://acm.hdu.edu.cn/showproblem.php?pid=4405 题意:每次可以走1~6格,初始化在第0格,走到>=n的格子就结束.还有m个传送门,表示可以从X[i] ...

  8. SQLServer 客户端远程访问配置

    SQL2008报错“请验证实例名称是否正确并且SQL Server已配置为允许远程连接” 第一步: 连接远程服务器时SQL2008报错“请验证实例名称是否正确并且SQL Server已配置为允许远程连 ...

  9. A quick tour of JSON libraries in Scala

    A quick tour of JSON libraries in Scala Update (18.11.2015): added spray-json-shapeless libraryUpdat ...

  10. daterangepicker 日期范围插件自定义 可选 年份

    minDate:'01/01/2012',maxDate:'01/01/2015' $("#txtPODate").daterangepicker({ singleDatePick ...