难得一逼的web基础

网络真心很抽象,真心很麻烦,Linux都比网络好玩。

1.通信

首先学了一个paramiko, 主要是其中的ssh和sftp. ssh是用来和远程的主机建立连接和通信,sftp可以接收或者发送文件到远程主机。

ssh的代码写法如下:

import paramiko
#SSH client
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname="192.168.43.123",port=22,username='liqing',password='1234')
stdin,stdout,stderr = ssh.exec_command('df')
result = stdout.read()
print(result)
ssh.close()

需要注意的是,ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())这句话最好都加上,保证将远程主机加到:known hosts这个文件中。

sftp的代码写法如下:

import paramiko
transport = paramiko.Transport(('192.168.80.130',22))
transport.connect(username='qq',password='1234')

sftp = paramiko.SFTPClient.from_transport(transport)
#从本地上传文件到远程端口
local_path = 'Z:李晴基础day 9 paramitolocation.py'
sftp.put(local_path,'/home/qq/Desktop/test.py')
#从远程端口下载文件
sftp.get('remove_path','local_path')
transport.close()

刚开始的时候,对这个hostname很不理解,因为我没有装Linux啊。其实是我根本不会Linux。为了实现代码和作业,只能装个虚拟机,然后装一个Linux系统。

2.线程(threading)

基本的概念:线程是一对代码的集合;进程是一堆资源的集合。进程是要通过线程才能执行的,所以进程的启动速度比线程要慢。但是运行之后,进程和线程的速度就没有区别了。线程可以创建子线程,父、子线程是相互独立的,所以父线程结束了,子线程还是会继续执行(除非把子线程设置为守护线程(t.setDaemon(True)))。 但是父进程和子进程就是有关系的,父进程结束了,子进程也跟着结束了。

2.1 锁(线程锁Mutex,GIL锁,递归锁)

Python有GIL锁,所以解释器某一个时段只能让一条python代码执行。但是,如果有多个线程同时修改一份数据,那么可能出现执行多次,数据错误的情况。原因是多个线程并发执行,所以拿到修改的数据可能就不是最新的。为了解决这个问题,就有threading.Lock。也可以通过设置信号量来设置线程数量(semaphore (信号量))。

2.2 event, queue

如果遇到多个线程,那么怎么在线程之间执行切换呢?

方法1:手动切换。用event, 在线程1中的某处设置event.set(),然后线程2去检查,如果event是set格式,那么执行A动作。然后线程1到了一定的时间清除event.clear(), 那线程2也就紧跟着执行了B动作。适用于两个线程,每个线程都有两种情况的模式。

方法2:是一个有序的容器,可以实现程序的解耦。(使得程序之间相互的依靠性下降,更加独立)queue.

q = queue.Queue(maxsize=3) #常规的模式是先入先出

q2 = queue.LifoQueue(maxsize=3) #后入先出

q3 = queue.PriorityQueue(maxsize=4) #可以在放的时候设置一下优先级,那么取出的时候就会根据优先级来:q3.put((10,'alex'))

3.进程(multiprocessing)

两个线程是共享内存空间的,所以他们的数据是可以进行相互交换的;但是两个进程是有独立的内存空间的,所以不能共享数据。那要是需要实现两个进程之间的数据交换,应该如何处理呢?需要创建“纽带

3.1 pipe,Queue, Manager()

pipe 需要定义parent_pipe, child_pipe = pipe() 这两个管道; 在创建子进程的时候,就将管子传给子进程: p= Process(target = f, args= (child_pipe,) ); parent_pipe 发送数据,child_pipe接受数据,反之亦然。

Queue 需要父进程定义一个q=Queue(); 然后创建子进程的时候,将这个q传给子进程 p=Process(target = f, args=(q,))。之后子进程可以向父进程的q放入数据,父进程通过q拿到数据。

Manager可以生成一个在进程中共享的字典或者列表。d= Manager.dict(), l = Manager.list()

for i in range(10)

p = Process(target=f, args=(d,l))

p.start()

def f(d,l)

  d[os.getpid()] = os.getpid()

  l.append(os.getpid())

这样当10个进程执行完毕之后,d和l中就会有10个进程的ID号。相当于每个进程读取了相同的文件,然后对文件进行了修改。

3.2 进程池(锁)

那么多个进程在执行的时候,会不会也两个进程同时执行呢?答案是:“”。但是两个进程同时执行,最终结果是不会错误的,但是可能会引起屏幕输出混乱。所以进程中通过进程池来控制进程的数量:

from multiprocessing import Pool, Process,freeze_support
import time
import os

def Foo(i):
    time.sleep(2)
    print("in process",os.getpid())
    return i + 100

def Bar(arg):
    print("--> exec done:",arg)

if __name__ == '__main__': #如果是主动执行这个脚本,那么就执行;如果是被动执行这个脚本,那么下面的代码就不执行。
    pool = Pool(5) #允许进程池中最大放入5个进程
    for i in range(10):
        # pool.apply(func= Foo,args=(i,)) #有两种实用方法, apply是串行,apply_async是并行
        pool.apply_async(func=Foo, args=(i,),callback=Bar) #callback回调,等进程执行结束后,自动执行。回调是主进程执行的。

    print('end')
    pool.close()
    pool.join() #等进程池执行中的进程执行完毕之后再关闭,如果不写,那么程序直接关闭。

 

所以根据线程和进程的锁情况,总结了一下:

            线程                进程

生成方式   lock = threading.Rlock()        lock = Lock()

启动方式   lock.acquire()             lock.acquire()

释放方式   lock.release()             lock.release()

作用          防止线程之间使用数据混乱                       防止进程抢着在屏幕上打印数据,出现打印数据的混乱

原文地址:https://www.cnblogs.com/little-hunter/p/6519044.html