Dayday up ---- python Day9

Paramiko 模块

该模块基于SSH用于连接远程服务器并执行相关操作

SSH

在linux里面ssh传输可以输入密码来执行命令,python里面也可以用Paramiko实现

# --*--coding:utf-8--*--
import paramiko

# 创建 ssh 对象
ssh = paramiko.SSHClient()  # 用于连接远程服务器并执行基本命令
# 允许连接不再know_hosts文件的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())  
ssh.connect(hostname='172.16.19.221', port=28081, username='root', password='P0o9i8u7')
# stdin,stdout,stderr = ssh.exec_command('top -bn 1')
# 如果同时执行 多条命令:
stdin,stdout,stderr = ssh.exec_command('top -bn 1;df -hT')  # 执行命令

# result = stdout.read()
# result_err = stderr.read()

res,err = stdout.read(),stderr.read()
result = res if res else err    # 三元运算
# 解释: 如果 结果为res 则result = res 否则 result = err

print(result.decode())
# print(result_err.decode())
ssh.close()

或者:

import paramiko
transport = paramiko.Transport(('172.16.19.221',28081)) transport.connect(username='root',password='P0o9i8u7') ssh = paramiko.SSHClient() ssh._transport = transport stdin, stdout, stderr = ssh.exec_command('df') print(stdout.read().decode()) transport.close()    

回忆一下三元运算

# 三元运算
# 变量名 = 变量1 if 条件判断成立 else 变量2
# 条件成立 变量名值为变量1 否则 为变量2
#
# eg:

a = 1
b = 2
k = a if a < b else b
print(k)

# 等同于:
if a < b:
    k = a
    print("a<b",k)
else:
    k = b
    print(k)

那如果想实现ssh密钥登陆或者传输怎么实现呢?

机制:

公钥 public key 给对方

私钥 private key 自己留着

注: 在windows 里面没有ssh,如果想要生成id_rsa可以使用XShell工具 生成或者 从linux服务器拷贝到windows机器  

# --*--coding:utf-8--*--
import paramiko

# 指定 密钥文件
private_key = paramiko.RSAKey.from_private_key_file('id_rsa')

# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不再know_hosts文件的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='172.16.19.221', port=28081, username='root',pkey=private_key)
# 执行命令
stdin, stdout, stderr = ssh.exec_command('df;ls -l')

res,err = stdout.read(),stderr.read()
result = res if res else err

print(result.decode())

ssh.close()

SFTP  

 基于明文

# --*--coding:utf-8--*--
import paramiko

transport = paramiko.Transport(('172.16.19.221', 28081))

transport.connect(username='root', password='P0o9i8u7')
sftp = paramiko.SFTPClient.from_transport(transport)  # SFTPClient 用于连接远程服务器并执行上传下载

# 上传到服务器
# sftp.put('hello', '/tmp/hello')

# 下载服务器文件
sftp.get('/root/anaconda-ks.cfg', 'anaconda-ks.cfg')

transport.close()

基于密钥

# --*--coding:utf-8--*--

import paramiko
# 指定 密钥文件
private_key = paramiko.RSAKey.from_private_key_file('id_rsa')

transport = paramiko.Transport(('172.16.19.221', 28081))
transport.connect(username='root', pkey=private_key)

sftp = paramiko.SFTPClient.from_transport(transport)

sftp.put('id_rsa', '/tmp/id_rsa')

sftp.get('/root/build.sh.bak', 'build.sh.bak')

transport.close()

例子:

# --*--coding:utf-8--*--
import paramiko
import uuid

class Ssh_eg(object):

    def __init__(self):
        self.host = '172.16.19.221'
        self.port = 28081
        self.username = 'root'
        self.__k = None

    def create_file(self):
        file_name = str(uuid.uuid4())
        with open(file_name,'w') as f:
            f.write('dayday')
        return file_name

    def run(self):
        self.connect()
        self.upload()
        self.rename()
        self.close()

    def connect(self):
        private_key = paramiko.RSAKey.from_private_key_file('id_rsa')
        transport = paramiko.Transport((self.host,self.port))
        transport.connect(username=self.username,pkey=private_key)
        self.__transport = transport

    def close(self):

        self.__transport.close()

    def upload(self):
        # 连接,上传
        file_name = self.create_file()

        sftp = paramiko.SFTPClient.from_transport(self.__transport)
        # 将sftp_明文.py 上传至服务器 /tmp/sftp_明文.py
        sftp.put(file_name, '/root/%s' % file_name)

    def rename(self):

        ssh = paramiko.SSHClient()
        ssh._transport = self.__transport
        # 执行命令
        stdin, stdout, stderr = ssh.exec_command('mv /root/tttttttttttt.py /root/ooooooooo.py')
        # 获取命令结果
        result = stdout.read()


ha = Ssh_eg()
ha.run()
ssh

 

多线程和多进程 

线程:  是一串指令的集合,是操作系统最小的调度单位,包含在进程之中

  一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并发执行不同的任务

进程: 一个执行程序的实例就叫做进程

  要以一个整体的形式暴露给操作系统管理,里面包含对各种资源的调用,比如: 内存的管理,网络接口的调用等

  对各种资源管理的集合就可以成为进程

进程与线程的关系:

1、进程要操作cpu等资源就必须先创建一个线程

2、进程不可以执行,因为它只是资源的集合,操作cpu是通过线程来执行的

3、cpu单核只能干一件事,因为它的速度特别快,所以让我们觉得它在做多见识,实际只有一个cpu在运行

4、所有在同一个进程的线程都是共享一块内存空间的,但线程是互相独立的,但进程不是,如果一个线程杀掉了,另一个线程还是正常独立

5、同一个进程的线程之间可以直接交流,但两个进程想通信必须通过一个中间代理来实现

6、创建新线程很简单,创建新进程需要对其父进程进行一次克隆

7、一个线程可以控制和操作同一个进程里面的其它线程,但进程只能操作子进程

8、对主线程的修改(比如修改优先级,取消等)可能会影响一个进程的其他线程,而父进程的修改不会影响子进程

 

多线程实例:

# --*--coding:utf-8--*--
# 方式1
import threading,time
def ha(n):   #定义每个线程要运行的函数
    print('task,',n)
    time.sleep(2)

t1 = threading.Thread(target=ha,args=("t1",))  # 生成一个线程实例
t2 = threading.Thread(target=ha,args=("t2",))
t1.start()   # 启动线程
t2.start()
print(t2.getName())   #  获取线程名

# 方式2 继承式调用
import threading,time

class MyThread(threading.Thread):
    def __init__(self,n):
        super(MyThread,self).__init__()
        self.n = n

    def run(self):     # 函数名必须为run,继承threading.Thread
        print("runnint task", self.n )
        time.sleep(2)


t1 = MyThread("t1")
t2 = MyThread("t2")

t1.start()
t2.start()

如果有50个进程一块进行呢?

# --*--coding:utf-8--*--
import threading,time
def run(n):
    print("task...", n)
    time.sleep(2)

start_time = time.time()
t_objs = []
for i in range(50):
    t = threading.Thread(target=run,args=("t-%s" % i,))
    t.start()
    t_objs.append(t)   #为了不阻塞后面线程的启动,不在这里join,先放到一个列表里

for t in t_objs:   #循环线程实例列表,等待所有线程执行完毕
    t.join()    # 如果一个线程或者在函数执行的过程中调用另一个线程,并且希望待其完成操作后才能执行,那么在调用线程的时就可以使用被调线程的join方法join([timeout])

print("----------all threads has finished----------------")
print("cost:",time.time()-start_time)
threading.active_count() 统计当前有多少进程在执行
threading.current_thread() 当前的进程名
 

 守护线程:

如果你将进程设置成了守护进程,那么表示你在说这个线程是不重要的,在进程退出的时候,不用等待这个线程退出

如果你的主线程在退出的时候,不用等待那些子线程完成,那就设置这些线程的daemon属性。即,在线程开始(thread.start())之前,调用setDeamon()函数,设定线程的daemon标志。(thread.setDaemon(True))就表示这个线程“不重要”。

如果你想等待子线程完成再退出,那就什么都不用做,或者显示地调用thread.setDaemon(False),设置daemon的值为false。新的子线程会继承父线程的daemon标志。整个Python会在所有的非守护线程退出后才会结束,即进程中没有非守护线程存在的时候才结束。

 # 设置守护进程之前
import threading,time
def fun(n):
    print("start fun - %s" % n)
    time.sleep(2)
    print("end fun - %s" % n)

print("main thread start")
t1 = threading.Thread(target=fun,args=("t1",))
# t1.setDaemon(True)
t1.start()
time.sleep(1)
print("main thread end")

结果>>>:
main thread start
start fun - t1
main thread end
end fun - t1

# 设置守护进程之后
import threading,time
def fun(n):
    print("start fun - %s" % n)
    time.sleep(2)
    print("end fun - %s" % n)

print("main thread start")
t1 = threading.Thread(target=fun,args=("t1",))
t1.setDaemon(True)   # 把当前线程设置为守护线程
t1.start()
time.sleep(1)
print("main thread end")

结果>>>:
main thread start
start fun - t1
main thread end

进程退出的时候不会等待这个守护线程

 

在python中不管cpu有多少核,同一时间执行的都是一个线程,多线程都是假象,只是因为cpu不断的进行上下文的切换

 这是cpython的一个缺陷,GIL ,但 GIL并不是python的特性,是cpython  解释器,未来的pypy会成为python的解释器,这个缺陷就会没有了

python 的线程是调用系统的原生线程

注意: time.sleep 的时候不占用cpu

 

线程锁(互斥锁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)

正常来说,我们想要的结果应该是0,但在python2上多运行几次,结果不总是0,如图:  

为什么会这样呢?

假设你有A,B两个线程,此时都 要对num 进行减1操作, 由于2个线程是并发同时运行的,所以2个线程很有可能同时拿走了num=100这个初始变量交给cpu去运算,当A线程去处完的结果是99,但此时B线程运算完的结果也是99,两个线程同时CPU运算的结果再赋值给num变量后,结果就都是99

那怎么办?

每个线程在要修改公共数据时,为了避免自己在还没改完的时候别人也来修改此数据,可以给这个数据加一把锁, 这样其它线程想修改此数据时就必须等待你修改完毕并把锁释放掉后才能再访问此数据。 

# --*--coding:utf-8--*--
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)

  

 RLock (递归锁)

连续锁很多次的时候,用递归锁,就是在一个大锁中还要再包含子锁

线程锁(互斥锁)同时只允许一个线程修改数据

比如: 平常进入家里,首先有一条大门,进入大门之后得关上大门再进入房间,进入房间再关上门,就是说同一时间大门和房间门都是关上的

# --*--coding:utf-8--*--
import threading,time

def run1():
    print("first......!")
    lock.acquire()
    global num
    num +=1
    lock.release()
    return num

def run2():
    print("second......!")
    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)

num,num2 = 0,0
# lock = threading.Lock()
lock = threading.RLock()   # 创建递归锁

for i in range(10):
    t = threading.Thread(target=run3)
    t.start()

while threading.active_count() != 1:    # 不等于1,即子线程都还没有执行完
    print(threading.active_count())
else:
    print('----all threads done---')

结果:

first......!
------------between run1 and run2---------
second......!
1 1
first......!
------------between run1 and run2---------
second......!
2 2
first......!
------------between run1 and run2---------
second......!
3 3
first......!
------------between run1 and run2---------
second......!
4 4
first......!
------------between run1 and run2---------
second......!
5 5
first......!
------------between run1 and run2---------
second......!
6 6
first......!
------------between run1 and run2---------
second......!
7 7
first......!
------------between run1 and run2---------
second......!
8 8
first......!
------------between run1 and run2---------
second......!
9 9
first......!
------------between run1 and run2---------
2
second......!
10 10
----all threads done---

  

信号量(Semaphore)

互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据

比如: 会议室里面有三个面试官,一个人面试一个就业者,如果一个就业者面试完出来了那么就再进去一个,意思就是会议室里面可以同时有三个就业者面试 

# --*--coding:utf-8--*--

import threading,time

def run(n):
    semaphore.acquire()
    time.sleep(2)
    print("run the thread:",n)
    semaphore.release()

semaphore = threading.BoundedSemaphore(3)  # 创建信号量实例

for i in range(11):
    t = threading.Thread(target=run,args=(i,))
    t.start()

while threading.active_count() != 1:
    pass
else:
    print("all theads done")

结果:

run the thread: 1
run the thread: 0
run the thread: 2

run the thread: 3
run the thread: 5
run the thread: 4

run the thread: 8
run the thread: 6
run the thread: 7

run the thread: 9
run the thread: 10
all theads done

 

events

是一个简单的同步对象

代表一个内部的标志和线程,可以等待这个标志被设置、设置、或者清楚标志本身

import threading
event = threading.Event() # 创建event 实例,同步对象
event.set()  # 设定标志位  如果设定标志位,这个等待的方法不能做任何事情 即 代表绿灯,直接通行
event.wait()  # 等待标志位 即等待变绿灯
event.clear() # 清空标志位 如果标志位被清空了, 将被锁定直到再次设定标志位 即 代表红灯

使用event来模拟红绿灯  

 

# --*--coding:utf-8--*--
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;1mred light is on....\033[0m")
        elif count > 10:
            event.set()   # 设置标志位  绿灯
            count = 0   # 重置次数 即从这开始循环
        else:
            print("\033[42;1mgreen light is on....\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] sees red light , waiting...." % name)
            event.wait()  # 等待标志位被设定
            print("\033[34;1m[%s] green light is on, start going...\033[0m" % name)


light = threading.Thread(target=lighter,)
light.start()

car1 = threading.Thread(target=car,args=("Tesla",))
car1.start()

event门禁实例: 员工进公司门要刷卡, 我们这里设置一个线程是“门”, 再设置几个线程为“员工”,员工看到门没打开,就刷卡,刷完卡,门开了,员工就可以通过。

# --*--coding:utf-8--*--
import threading,time,random

door_swiping_event = threading.Event()
def door():
    door_open_time_counter = 0
    while True:
        if door_swiping_event.is_set():
            print("\033[32;1mdoor opening....\033[0m")

        else:
            print("\033[31;1mdoor closed...., swipe to open.\033[0m")
            door_open_time_counter = 0  # 清空计时器
            door_swiping_event.wait()

        if door_open_time_counter > 3:
            door_swiping_event.clear()

        time.sleep(1)
        door_open_time_counter += 1

def staff(n):
    print("staff [%s] is comming..." % n)
    while True:
        if door_swiping_event.is_set():
            print("\033[34;1mdoor is opened, passing.....\033[0m")
            break
        else:
            print("staff [%s] sees door got closed, swipping the card....." % n)
            print(door_swiping_event.set())
            door_swiping_event.set()
            print("after set", door_swiping_event.set())

        time.sleep(1)

door_thread = threading.Thread(target=door)
door_thread.start()

for i in range(5):
    staff_thread = threading.Thread(target=staff,args=(i,))
    time.sleep(random.randrange(3))
    staff_thread.start()


结果:
door closed...., swipe to open.
staff [0] is comming...
staff [0] sees door got closed, swipping the card.....
None
after set None
staff [1] is comming...
door is opened, passing.....
door is opened, passing.....
staff [2] is comming...
door is opened, passing.....
door opening....
door opening....
door opening....
staff [3] is comming...
door is opened, passing.....
door opening....
staff [4] is comming...
staff [4] sees door got closed, swipping the card.....
None
after set None
door is opened, passing.....
door opening....
door closed...., swipe to open.

    

queue 队列

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

作用:

1、程序的结耦

2、提高运行效率 

queue是相当于一个容器,但是是有顺序的

python2 : import Queue

python3 : import queue

python queue模块有三种队列并且对应三种构造函数 :

  class queue.Queue(maxsize=0) #先入先出

  class queue.LifoQueue(maxsize=0) #last in fisrt out  后入先出

  class queue.PriorityQueue(maxsize=0) #存储数据时可设置优先级的队列

 构造函数为一个优先队列,maxsize是设置最大尺寸,最大能放多少个数,如果最大尺寸小于或者等于零,队列大小是无限的

queue.qsize()  # 返回队列大小
queue.empty() #return True if empty  如果队列为空,返回True,反之False 
queue.full() # return True if full 如果队列满了,返回True,反之False
queue.put(itemblock=Truetimeout=None)  # 将一个值放入队列中

queue.put_nowait(item)  #相当queue.put(item, False)

queue.get(block=Truetimeout=None)    # 从队列中取出值

 

queue.get_nowait()  #相当queue.get(False)

queue.task_done()  #在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号

queue.join()  # block直到queue被消费完毕 实际上意味着等到队列为空,再执行别的操作

  

# 先入先出
import queue

q = queue.Queue()  # 默认maxsize  = 0 先入先出
q.put("hello")  # 先入
q.put("dayday")

print(q.get()) # 先出
print(q.get())

结果>>>:
hello
dayday

# 后入先出
import queue
q = queue.LifoQueue()  # 后入先出
q.put("AB")
q.put("ab")

print(q.get())
print(q.get())

结果>>>:
ab
AB

# 设置优先级队列
import queue
q = queue.PriorityQueue()
q.put((-1,"a"))
q.put((12,"e"))
q.put((3,"b"))
q.put((10,"c"))
q.put((6,"d"))

print(q.get())
print(q.get())
print(q.get())
print(q.get())
print(q.get())

结果>>>:
(-1, 'a')
(3, 'b')
(6, 'd')
(10, 'c')
(12, 'e')

  

生产者消费者模型

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

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

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

什么是生产者消费者模式

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

例1:

# --*--coding:utf-8--*--
import threading,queue,time

q = queue.Queue()
def producer():
    count = 1
    while True:
        q.put("第%s碗饭" % count)   # 生产者放入队列
        print("生产了米饭",count)
        count +=1
        time.sleep(0.5)

def consumer(n):
    while True:
        print("%s 取到" % n, q.get())   # 消费者从队列取
        q.task_done()
        time.sleep(1)

p = threading.Thread(target=producer,)
p.start()

c1 = consumer("顾客1")
c2 = consumer("顾客2")

例2:

# --*--coding:utf-8--*--
import time,random
import queue,threading
q = queue.Queue()
def Producer(name):
  count = 0
  while count < 20:
    time.sleep(random.randrange(3))
    q.put(count)
    print('Producer %s has produced %s baozi..' %(name, count))
    count +=1

def Consumer(name):
  count = 0
  while count <20:
    time.sleep(random.randrange(4))
    if not q.empty():
        data = q.get()
        print(data)
        print('\033[32;1mConsumer %s has eat %s baozi...\033[0m' %(name, data))
    else:
        print("-----no baozi anymore----")
    count +=1

p1 = threading.Thread(target=Producer, args=('A',))
c1 = threading.Thread(target=Consumer, args=('B',))
p1.start()
c1.start()

  

  

 

posted @ 2016-09-21 17:29  a_monologue  阅读(93)  评论(0)    收藏  举报