一、paramiko模块

paramiko模块是一个遵循ssh2协议的python扩展模块,该模块可以允许使用python通过ssh协议去远程管理主机。在使用该模块前,需要手动安装,具体安装过程请百度,这里不再赘述。

通过paramiko模块不仅可以远程连接主机执行命令,还可以远程传输文件,类似与scp功能。接下来我们分别来看一下使用paramiko模块来实现模拟ssh和scp这两个功能的实现步骤及代码:

模拟ssh登录的步骤:

1、实例化一个ssh对象:ssh = paramiko.SSHClient

2、保存远程主机的公钥信息到known_hosts文件中:ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

3、连接主机:ssh.connect(hostname="IP",port="端口",username="用户名",password="密码")

4、收集命令标准输入、标准输出、标准错误信息:stdin,stdout,stderr = ssh.exec_command('命令')

5、处理命令输出结果

6、关闭连接:ssh.close()

#!/usr/bin/env python3

#-*- coding:utf-8 -*-__Author__= "ZHY"import paramiko

ssh=paramiko.SSHClient()

ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

ssh.connect(hostname='10.1.16.203',port=22,username="zhanghaoyan",password="zhy200")

stdin,stdout,stderr= ssh.exec_command("top")

res,err=stdout.read(),stderr.read()

result= res if res elseerr

print(result.decode())

ssh.close()

ssh密码认证

模拟scp传文件的步骤:

1、实例化一个transport对象:transport = paramiko.Transport(('hostname',port))

2、连接服务器:transport.connect(username='用户名',password='密码')

3、将该transport实例作为参数传递给SFTPClient.from_transport()来创建一个sftp实例:sftp = paramiko.SFTPClient.from_transport(transport)

4、上传文件/下载文件:sftp.put("本地文件","目标路径")/sftp.get("目标路径","本地路径")

5、关闭连接:transport.close()

#!/usr/bin/env python3#-*- coding:utf-8 -*-

__Author__ = "ZHY"

importparamiko

transport= paramiko.Transport(('10.1.16.203',22))

transport.connect(username="zhanghaoyan",password='zhy200')

sftp=paramiko.SFTPClient.from_transport(transport)

sftp.put("./note","/tmp/note.txt") #上传文件#sftp.get("/home/zhanghaoyan/codes/a.txt","./") #下载文件

transport.close()

传输文件

paramiko模块还可以使用秘钥认证的方式去登陆管理服务器,实现步骤如下:

1、指定本地公钥文件:pri_key = paramiko.RSAKey.from_private_key_file("公钥文件路径")

2、连接时password参数改为pkey参数,传入上述定义的公钥文件变量ssh.connect(hostname="IP地址",port=端口号,username="用户名",pkey=秘钥变量)

3、其余步骤参照上述ssh部分

#!/usr/bin/env python3#-*- coding:utf-8 -*-

__Author__ = "ZHY"

importparamiko

pri_key= paramiko.RSAKey.from_private_key_file("/home/zhanghaoyan/.ssh/id_rsa")

ssh=paramiko.SSHClient()

ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

ssh.connect(hostname="10.1.16.203",port=22,username="zhanghaoyan",pkey=pri_key)

stdin,stdout,stderr= ssh.exec_command("ls")

res,err=stdout.read(),stderr.read()

result= res if res elseerrprint(result.decode())

ssh.close()

免密码ssh认证

#!/usr/bin/env python3#-*- coding:utf-8 -*-

__Author__ = "ZHY"

importparamiko

pri_key= paramiko.RSAKey.from_private_key_file("/Users/zhanghaoyan/.ssh/id_rsa")

transport= paramiko.Transport(('10.1.16.203',22))

transport.connect(username="zhanghaoyan",pkey=pri_key)

sftp=paramiko.SFTPClient.from_transport(transport)

sftp.put("./note","/tmp/note.txt")

transport.close()

免密码scp传输文件

二、线程

1、什么是线程

线程就是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

A thread is an execution context, which is all the information a CPU needs to execute a stream of instructions.Suppose you're reading a book, and you want to take a break right now, but you want to be able to come back and resume reading from the exact point where you stopped.One way to achieve that is by jotting down the page number, line number, and word number.So your execution context for reading a book is these 3 numbers.If you have a roommate, and she's using the same technique, she can take the book while you're not using it, and resume reading from where she stopped.Then you can take it back, and resume it from where you were.

Threads work in the same way.

A CPU is giving you the illusion that it's doing multiple computations at the same time.It does that by spending a bit of time on each computation.It can do that because it has an execution context for each computation.Just like you can share a book with your friend, many tasks can share a CPU.On a more technical level, an execution context (therefore a thread) consists of the values of the CPU's registers.

Last: threads are different from processes.

A thread is a context of execution, while a process is a bunch of resources associated with a computation.

A process can have one or many threads.

Clarification: the resources associated with a process include memory pages (all the threads in a process have the same view of the memory), file descriptors (e.g., open sockets), and security credentials (e.g., the ID of the user who started the process).

上面这段话的意思是:

一个线程是一个可执行的上下文,这个上下文就是CPU在执行一个指令流时需要的所有信息。假设你正在读一本书,而且你现在想暂停一下,但是你想过一会儿会来从你停下的地方继续阅读这本书。一种方法就是你记下来停止时的页码,行号以及第几个字。所以,你可以使用这三个数字的上下文来执行读书这件事。如果你有一个室友,她也使用这样的方法,那么她就能在你不读这本书的时候来读,而且还可以从她上次中断的地方继续读。然后,你可以把书拿回来,从上次中断的地方继续。

线程就是这么执行的。

CPU给人一种幻觉,那就是它在同一时间同时执行了多个任务。CPU通过给每个任务一点运行时间来实现这一点。CPU可以完成这一点就是因为它给每个计算任务都记录并执行了上下文。就像你可以和你的朋友共享一本书一样,多任务可以共享一个CPU。在深层次的技术层面,一个可执行的上下文(就是一个线程)由CPU寄存器中的值组成。

最后,线程和进程是不一样的。

一个线程是一个可执行的上下文,一个进程是一组计算资源的集合。

一个进程可以有一个或多个线程。

声明:与进程相关的资源包括内存页(同一个进程中的所有线程共享内存),文件描述符和安全认证

2、什么是进程

An executing instance of a program is called a process.

Each process provides the resources needed to execute a program. A process has a virtual address space, executable code, open handles to system objects, a security context, a unique process identifier, environment variables, a priority class, minimum and maximum working set sizes, and at least one thread of execution. Each process is started with a single thread, often called the primary thread, but can create additional threads from any of its threads.

一个程序的可执行实例称为一个进程。

每个进程提供了程序运行所需的资源。一个进程拥有一个虚拟地址空间,可执行代码,打开操作系统对象的句柄,一个安全上下文,一个唯一的进程标识符,环境变量,优先级,最大和最小的运行空间和至少一个可执行线程。每个进程从一个线程开始,通常称为主线程,但是可以从其任何一个线程来创建新线程。

3、线程和进程的区别

1)、Threads share the address space of the process that created it; processes have their own address space.

2)、Threads have direct access to the data segment of its process; processes have their own copy of the data segment of the parent process.

3)、Threads can directly communicate with other threads of its process; processes must use interprocess communication to communicate with sibling processes.

4)、New threads are easily created; new processes require duplication of the parent process.

5)、Threads can exercise considerable control over threads of the same process; processes can only exercise control over child processes.

6)、Changes to the main thread (cancellation, priority change, etc.) may affect the behavior of the other threads of the process; changes to the parent process does not affect child processes.

1)、线程共享其所属进程的地址空间;进程拥有各自独立的地址空间

2)、线程可以直接访问进程的数据段;进程从其父进程拷贝一份数据

3)、同一个进程中的所有线程之间可以直接通信;进程必须通过第三方中间件来进行通信

4)、新线程很容易创建;新进程需要从父进程进行复制

5)、线程可以很容易控制同一进程中的其他线程;进程只能控制其子进程

6)、对于主线程的修改,有可能会影响到同一进程中其他线程的运行;改变父进程的修改,不会影响其他子进程

4、写一个多线程的程序

#!/usr/bin/env python3#-*- coding:utf-8 -*-

__Author__ = "ZHY"

importthreading,timedefrun(n):print("running threading:",n)

time.sleep(2)for i in range(10):

t= threading.Thread(target=run,args=(i,))

t.start()

运行结果:

running threading: 0

running threading:1running threading:2running threading:3running threading:5running threading:4running threading:6running threading:7running threading:8running threading:9

从上述代码中我们可以看到,创建多线程需要使用threading这个模块,创建多线程的基本步骤如下:

1)、导入threading模块

2)、定义多线程要执行的任务

3)、创建线程实例:t = threading.Thread(target="函数名",args=(参数1,参数2,...))

4)、启动线程:t.start()

5、join()

上述代码中我们看到,所有线程基本是在同时执行的,那如果我们想看看所有线程执行完成所用的时间的话如何实现呢?先看代码:

#!/usr/bin/env python3#-*- coding:utf-8 -*-

__Author__ = "ZHY"

importthreading,timedefrun(n):print("running threading:",n)

time.sleep(2)print("threading %s done" %n)

time_start=time.time()for i in range(10):

t= threading.Thread(target=run,args=(i,))

t.start()print("----------------------------------")print("cost:" ,(time.time() -time_start))

运行结果:

running threading: 0

running threading:1running threading:2running threading:3running threading:4running threading:5running threading:6running threading:7running threading:8running threading:9

----------------------------------cost:0.0018157958984375threading1done

threading4done

threading2done

threading9done

threading3done

threading6done

threading5done

threading 0 done

threading7done

threading8 done

WTF?!这样的结果是为什么?我们从运行结果上可以看到,线程启动完成后,我们的程序并没有等待线程执行结束就继续向下执行了,这是因为我们程序的主线程并不会等待子线程执行完毕就会继续向下执行导致的,如果需要让主线程等待子线程执行完毕,那就需要用到一个方法:join()方法:

#!/usr/bin/env python3#-*- coding:utf-8 -*-

__Author__ = "ZHY"

importthreading,timedefrun(n):print("running threading:",n)

time.sleep(2)print("threading %s done" %n)

t= threading.Thread(target=run,args=(1,))

t.start()

t.join()print("----------------------------------")

运行结果:

running threading:1threading1done----------------------------------

从上述代码中我们可以看到,主线程的确在等待子线程结束完成后才继续执行,那么是多线程呢?如何让主线程等待子线程呢?答案是,我们将所有的线程实例都放入一个列表,线程启动后再去循环这些列表就可以了:

#!/usr/bin/env python3#-*- coding:utf-8 -*-

__Author__ = "ZHY"

importthreading,timedefrun(n):print("running threading:",n)

time.sleep(2)print("threading %s done" %n)

time_start=time.time()

t_list=[]for i in range(10):

t= threading.Thread(target=run,args=(i,))

t.start()

t_list.append(t)for j int_list:

j.join()print("----------------------------------")print("cost:" ,(time.time() -time_start))

运行结果:

running threading: 0

running threading:1running threading:2running threading:3running threading:4running threading:5running threading:6running threading:7running threading:8running threading:9threading 0 done

threading5done

threading8done

threading4done

threading1done

threading2done

threading3done

threading6done

threading7done

threading9done----------------------------------cost:2.003788948059082

6、守护线程

在上述代码中,我们使用join()让主线程等待所有子线程执行完毕后再继续执行,如果不适用join()方法的话,主线程就会和子线程一起并发的执行,而且可以看到,主线程执行完毕后程序并没有直接退出,而是等待所有子线程都执行完毕后程序才退出,那么问题就来了,如果在一个程序中,一个子线程负责监听一个端口,那如果这个程序挂了,但是子线程却没有退出,就会导致这个端口被占用,那有没有一个方法,可以在程序退出的时候不论子线程执行完毕与否,都自动结束子线程呢?答案是有的,那就是守护线程:

将一个线程设置为守护线程后,那这个线程所在的主线程在退出后,该子线程就会立即退出。

来我们看代码:

#!/usr/bin/env python3#-*- coding:utf-8 -*-

__Author__ = "ZHY"

importthreading,timedefrun(i):print("start task:", i)

time.sleep(2)print("task %s done" %i)for i in range(10):

t= threading.Thread(target=run,args=(i,))

t.setDaemon(True)

t.start()print("----------------Main thread is done----------------")

运行结果:

start task: 0

start task:1start task:2start task:3start task:4start task:5start task:6start task:7start task:8start task:9

----------------Main thread is done----------------

从上述代码可以看到,在启动线程前,使用setDaemon(True)方法就可以把这个线程设置为守护线程,主线程执行完毕后并没有等待子线程执行完毕,程序就立即退出了,这就是守护线程,这样的好处在于程序退出时,可以强制释放掉一些占用的系统资源,防止其变成僵尸线程。

7、GIL全局解释器锁

先来看多线程运行的两个概念:并发和并行

并发:当有多个线程在操作时,如果系统只有一个CPU(单核),则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间段分配给各个线程执行,在一个时间段的线程代码运行时,其它线程处于挂起状态。这种方式我们称之为并发(Concurrent)。

并行:当系统有一个以上CPU(或CPU有多核)时,则线程的操作有可能非并发。当一个CPU(或一个核)执行一个线程时,另一个CPU(或一个核)可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行(Parallel)。

并发和并行的区别就是一个处理器同时处理多个任务和多个处理器或者是多核的处理器同时处理多个不同的任务。前者是逻辑上的同时发生,而后者是物理上的同时发生。

python由于其设计之初的局限性,不借助三方库的情况下其多线程的实现采用的是并发的方式,而非并行的方式,这就意味着python代码在执行时无法完全利用cpu的计算资源,只可以在单个CPU上的单个核心中通过并发的方式执行,这也是python被人诟病最多的一点,说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 。

那么CPython实现中的GIL又是什么呢?GIL全称 Global Interpreter Lock 为了避免误导,我们还是来看一下官方给出的解释:

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.)

在CPython中,GIL是一个互斥锁,用于阻止多个线程同一时间执行python代码。这个锁是有必要的,因为CPython的内存管理机制不是线程安全的。(然而,由于有GIL存在,其他特性的开发已经都依赖于它了。)

为什么会存在GIL这个锁呢?GIL就是为了保证在同一时间,只有一个线程在运行,这也就确保了多线程并发执行的特性。

关于更多的GIL相关知识,可以看这篇文章:http://www.tuicool.com/articles/7zIra2r

8、互斥锁

python中虽然使用了GIL,但是在多线程中如果多个线程都要修改同一份数据,那么新的问题就出现了,我们来看代码:

#!/usr/bin/env python3#-*- coding:utf-8 -*-

__Author__ = "ZHY"

importthreadingdefrun():globalnum

num+= 1num=0

t_list=[]for i in range(1000):

t= threading.Thread(target=run)

t_list.append(t)

t.start()for j int_list:

j.join()print("num:",num)

python2中运行结果:

zhanghaoyandeMacBook:~zhanghaoyan$ python thread_lock.py

('num:', 1000)

zhanghaoyandeMacBook:~zhanghaoyan$ python thread_lock.py

('num:', 1000)

zhanghaoyandeMacBook:~zhanghaoyan$ python thread_lock.py

('num:', 1000)

zhanghaoyandeMacBook:~zhanghaoyan$ python thread_lock.py

('num:', 998)

zhanghaoyandeMacBook:~zhanghaoyan$ python thread_lock.py

('num:', 1000)

zhanghaoyandeMacBook:~zhanghaoyan$ python thread_lock.py

('num:', 1000)

注意上述代码执行结果中看到,有一次的执行结果是错误的,为什么会出现这个结果呢?不是已经有GIL了吗?这就是上面说过的多线程同时修改同一份数据的问题:

当线程1拿到初始数据,在修改该数据完成之前其CPU时间到期,导致其释放GIL,线程被挂起。

线程2被激活,同样拿到了还未被线程1修改的初始数据,但线程2在CPU时间到期之前就完成了修改数据的操作,此时,初始数据已经被修改。

线程1再次被激活时,不会重新拿取要修改的数据,而是根据上下文中的记录去继续未完成的操作,这时线程1再去修改初始数据,就会把线程2修改完的数据给覆盖掉,从而导致数据错误。

也正是由于上述过程的存在,才会导致多线程中修改同一份数据时可能出现数据异常的情况,那如何避免这种情况的发生呢,那就是通过加锁来确保同一份数据只有一个线程能修改,来看代码:

#!/usr/bin/env python3#-*- coding:utf-8 -*-

__Author__ = "ZHY"

importthreadingdefrun():

lock.acquire()#加锁

globalnum

num+= 1lock.release()#释放锁

lock= threading.Lock() #生成锁实例

num =0

t_list=[]for i in range(1000):

t= threading.Thread(target=run)

t_list.append(t)

t.start()for j int_list:

j.join()print("num:",num)

从上述代码中可以看到,我们在修改数据之前,先申请了一把锁,在修改数据完成之后,再释放这把锁,这样,就可以保证同一份数据同时只能有一个线程来修改,也就保证了数据的正确性。

9、递归锁

当一把锁中还有同样的另一把锁的时候,如果不使用递归锁,则会导致死锁现象,递归锁用法如下:初始化锁实例时使用threading.Rlock()方法即可

#!/usr/bin/env python3#-*- coding:utf-8 -*-

importthreading,timedefrun1():

lock.acquire()print("running run1")

lock.release()return 1

defrun2():

lock.acquire()print("running run2")

lock.release()return 2

defrun3():

lock.acquire()

res1=run1()print("run1 done")

res2=run2()print("run2 done")

lock.release()

lock=threading.RLock()for i in range(10):

t= threading.Thread(target=run3)

t.start()while threading.active_count() != 1:print("thread acount:", threading.active_count())else:print("all thread done")

10、信号量

我们还可以通过信号量来控制同时执行的最多线程数量,类似于线程池的概念:

#!/usr/bin/env python3#-*- coding:utf-8 -*-

importthreading,timedefrun(n):

sem.acquire()print("run:", n)

time.sleep(2)

sem.release()

sem= threading.BoundedSemaphore(5)for i in range(10):

t= threading.Thread(target=run,args=(i,))

t.start()while threading.active_count() != 1:continue

else:print("all thread done")

上述代码运行时可以看到,同时有5个线程进行。使用信号量的步骤与使用锁类似:

声明信号量:sem = threading.BoundedSemaphore(5)

线程申请信号量:sem.acquire()

运行完成后释放信号量:sem.release()

三、事件

上述多线程在运行的过程中都是独立运行的,如果一个线程执行需要另一个线程的执行结果来执行,也就是说线程之间需要通信,那怎么实现呢?这就需要用到事件的概念了,在一个线程执行中去设置一个事件标志位,另一个进程去判断这个事件标志位是否被设置,根据结果来做出相应的操作。

使用事件的步骤如下:

1、初始化事件实例

2、设置事件标志位/清空事件标志位

3、判断事件标志位,进行操作

写一个红绿灯的程序,红绿灯交替5秒,红灯亮时汽车停止通行,绿灯亮时汽车继续通行,来看代码:

#!/usr/bin/env python3#-*- coding:utf-8 -*-

importthreading,time

event= threading.Event() #初始化一个事件实例

deflight():

count=0whileTrue:if count <= 5:

event.set()#设置标志位,红灯亮

print("\033[41;1mRed light working!\033[0m",5-count)elif count > 5 and count < 11:

event.clear()#清除标志位,绿灯亮

print("\033[42;1mGreen light working!\033[0m",11-count)else:

count= -1count+= 1time.sleep(1)defcar():whileTrue:if event.is_set(): #判断标志位是否被设置

print("The red light working,stop and wait for green!")else:print("The green light working,keep going!")

time.sleep(1)

Light= threading.Thread(target=light)

Light.start()

car1= threading.Thread(target=car)

car1.start()

运行结果:

Red light working!5The red light working,stopand wait forgreen!

Red light working!4The red light working,stopand wait forgreen!

The red light working,stopand wait forgreen!

Red light working!3The red light working,stopand wait forgreen!

Red light working!2The red light working,stopand wait forgreen!

Red light working!1The red light working,stopand wait forgreen!

Red light working! 0

Green light working!5The green light working,keep going!

Green light working!4The green light working,keep going!

Green light working!3The green light working,keep going!

Green light working!2The green light working,keep going!

Green light working!1The green light working,keep going!

The green light working,keep going!

Red light working!5The red light working,stopand wait forgreen!

Red light working!4The red light working,stopand wait forgreen!

Red light working!3The red light working,stopand wait forgreen!

The red light working,stopand wait forgreen!

Red light working!2The red light working,stopand wait forgreen!

Red light working!1

红绿灯

四、队列

队列就是一个线性表,类似于列表或元组,都是有顺序的数据集合,但是队列和列表等其他数据类型有区别,队列保存在内存中,从队列中取出一个数据后该数据就从队列中删除掉了。

#!/usr/bin/env python3#-*- coding:utf-8 -*-

importqueue

q= queue.Queue(maxsize=10)for i in range(10):

q.put(i)print("q.qsize():",q.qsize())print("q.full():",q.full())print("q.empty():",q.empty())print(q.get())print("q.qsize():",q.qsize())print("q.full():",q.full())print("q.empty():",q.empty())

运行结果:

q.qsize():10q.full(): True

q.empty(): False

0

q.qsize():9q.full(): False

q.empty(): False

q = queue.Queue(maxsize=xx):声明一个先进先出的队列,maxsize参数用于指定队列大小

q = queue.LifoQueue(maxsize=xx):声明一个后进先出的队列

q = queue.PriorityQueue(maxsize=xx):声明一个有优先级的队列

q.put("data"):向队列中插入数据

q.get(block=False,timeout=1):从队列中取出数据,当队列中没有数据时,如果没有设置block和timeout参数,则程序会阻塞,block参数设置为False表示取不到数据时不阻塞,timeout表示取不到数据时阻塞的最长超时时间。

q.get_nowait():从队列中取数据,从不阻塞

q.qsize():返回队列长度

q.empty():如果队列为空,则返回True,否则返回False

q.full():如果队列满了,返回True,否则返回False

五、生产者消费者模型

#!/usr/bin/env python3#-*- coding:utf-8 -*-

importthreading,time,queue

shop= queue.Queue(maxsize=10)defProduce(product):

i=0whileTrue:print("produce product:", product,i)

shop.put("%s [%s]" %(product,i))

i+= 1time.sleep(0.1)defConsumer(name):whileTrue:print("%s get bone:%s" %(name,shop.get(timeout=1)))

time.sleep(1)

produce1= threading.Thread(target=Produce,args=("Bone",))

produce1.start()

consumer1= threading.Thread(target=Consumer,args=("zhangsan",))

consumer1.start()

运行结果:

produce product: Bone 0

zhangsan get bone:Bone [0]

produce product: Bone1produce product: Bone2produce product: Bone3produce product: Bone4produce product: Bone5produce product: Bone6produce product: Bone7produce product: Bone8produce product: Bone9zhangsan get bone:Bone [1]

produce product: Bone10produce product: Bone11produce product: Bone12zhangsan get bone:Bone [2]

……

python paramiko并发_python学习笔记9--paramiko模块、多线程、锁机制相关推荐

  1. python tkinter 表格_python学习笔记(Tkinter编程利用Treeview实现表格自动更新)

    博主今天总结这段时间抽空写的一个GUI编程项目 功能是查看本地打印机队列,可选择指定队列重新打印 直接上图 UI设计包括3个区域左上方,右上方和下方列表区域 使用网格grid方法来分配位置 下面是界面 ...

  2. python pow和**_Python学习笔记 | 实例3:天天向上的力量

    本文为中国大学MOOC<Python语言程序设计>课程学习笔记,课程主讲:嵩天老师,练习平台:Python123,参考教材:<Python语言程序设计基础> 天天向上的力量 加 ...

  3. python eval 入门_Python学习笔记整理3之输入输出、python eval函数

    Python学习笔记整理3之输入输出.python eval函数 来源:中文源码网    浏览: 次    日期:2018年9月2日 Python学习笔记整理3之输入输出.python eval函数 ...

  4. python分组求和_Python学习笔记之pandas索引列、过滤、分组、求和功能示例

    本文实例讲述了Python学习笔记之pandas索引列.过滤.分组.求和功能.分享给大家供大家参考,具体如下: 前面我们已经把519961(基金编码)这种基金的历史净值明细表html内容抓取到了本地, ...

  5. python图形设置_python学习笔记——基本图形绘制

    1.python蟒蛇python蟒蛇代码 #PythonDraw.py import turtle turtle.setup(650,350,200,200)# 设置画布的长.宽.起点 turtle. ...

  6. python dict遍历_Python学习笔记:19个pythonic编程习惯,让你的Python入门更优雅

    Python最大的优点之一就是语法简洁,好的代码就像伪代码一样,干净.整洁.一目了然. 要写出 Pythonic(优雅的.地道的.整洁的)代码,需要多看多学大牛们写的代码,github 上有很多非常优 ...

  7. python通信信号处理_python学习笔记——信号模块signal(示例代码)

    基于python学习笔记--多进程间通信--Linux信号基础的学习基础,进一步学习Python标准库中的signal模块. 尽管signal是python中的模块,但是主要针对UNIX平台(比如Li ...

  8. python编程计算器_Python学习笔记:用Python开发一个计算器项目

    最近抽空看了下python的学习文档,发现开发工具以及资料支持对开发者相当的友好,相比之下,以前用TCL&Tk做的项目主要缺点有两个:1,开发难度大,调试手段只有靠print一种,而且语法错误 ...

  9. python常用开放工具_python学习笔记16-各种模块和开放工具收集整理

    一.调试,性能,日志 Debugger: pdb Logger: logging Profilers: profile, hotshot, cProfile 调试模块 pdb 允许你设置(条件)断点, ...

最新文章

  1. CCAI 2020 | 唐剑:智慧交通,未来出行
  2. 数据库事务原理及并发、死锁
  3. 添加chorme插件时出现“程序包无效”
  4. 《Java 核心技术卷1 第10版》学习笔记 ------ 泛型【进阶】
  5. android 版本28 通知栏图标,【专题分析】应用图标、通知栏适配
  6. 岭回归预测PM2.5
  7. BZOJ 3238 【AHOI2013】 差异
  8. Atitit 读取音频音乐文件的bpm 目录 1.1. Librosa是一个用于音频、音乐分析、处理的python工具包, 1 1.2. \bpm.py 1 1.3. Echo 2 1.4. Cod
  9. ajax 将整个表单提交到后台处理
  10. ubuntu20.04 桌面文件和文件夹图标 丢失解决
  11. Celery介绍——手机短信异步发送
  12. 聊聊关于使用逻辑斯蒂回归的使用方法
  13. File.separator是什么?
  14. A New Approach for English-Chinese Named Entity Alignment(跨语言实体对齐)
  15. Newtonsoft解析Json文件
  16. FiberSIM 16 v16.0.1
  17. Adobe Audition CS6原生支持ape和flac
  18. for 和 if 的基础用法
  19. 「镁客·请讲」美好明天机器人张超:与其做雷同的机器人产品,不如不做
  20. autoHotkey---获取输入光标的位置,判断是否在文本输入状态

热门文章

  1. [转]Log4Net五步走
  2. python正则匹配空格+数字+空格_详解Python中正则匹配TAB及空格的小技巧
  3. leetcode 5 Longest Palindromic Substring Java JavaScript解法
  4. 苹果将在内华达州里诺市再购地块 都是为了它
  5. Oracle 计划新的移动 OpenJDK 项目
  6. 如何在linux当中,大量的添加用户
  7. 为未来元素添加点击事件的两种写法
  8. Mapxtreme Java 地图缩放,平移操作的原理和实现
  9. 并发下,使用redis防止数据重复插入(数据库未对表字段设置唯一情况下)
  10. 快速锁定Windows XP桌面的几个方法