python 学习第十一课 上下文管理 paramiko 堡垒机 mysql操作

Rlock Lock

这两种琐的主要区别是:RLock允许在同一线程中被多次acquire。而Lock却不允许这种情况。注意:如果使用RLock,那么acquirerelease必须成对出现,即调用了nacquire,必须调用n次的release才能真正释放所占用的琐

>>> help(threading.RLock)

RLock(*args, **kwargs)

    Factory function that returns a new reentrant lock.

    A reentrant lock must be released by the thread that acquired it. Once a 

    thread has acquired a reentrant lock, the same thread may acquire it again

    without blocking; the thread must release it once for each time it has

    acquired it.reentrant 再进去的,凹角的)

         import threading 

         lock = threading.Lock() #Lock对象 

         lock.acquire() 

         lock.acquire()  #产生了死琐。 

         lock.release() 

         lock.release() 

 

         import threading 

         rLock = threading.RLock()  #RLock对象 

         rLock.acquire() 

         rLock.acquire() #在同一线程内,程序不会堵塞。 

         rLock.release() 

         rLock.release() 

 

上下文管理器(context manager)

with   contextlib   yield

with

使用with…as .. 来打开文件,最后不需要显示的执行文件close,它会自动关闭文件,with就是一个简单的上下文管理器,它通过两个魔方方法来决定:

__enter__(self)

定义了当使用with语句的时候,会话管理器在块被初始创建事要产生的行为。请注意,__enter__的返回值与with语句的目标或者as后的名字绑定。

__exit__(self, exception_type, exception_value, traceback)

定义了当一个代码块被执行或者终止后,会话管理器应该做什么。它可以被用来处理异常、执行清理工作或做一些代码块执行完毕之后的日常工作。如果代码块执行成功,exception_typeexception_value,和traceback将会为None。否则,你可以选择处理这个异常或者是直接交给用户处理。如果你想处理这个异常的话,请确保__exit__在所有语句结束之后返回True。如果你想让异常被会话管理器处理的话,那么就让其产生该异常。

__enter____exit__对于那些定义良好以及有普通的启动和清理行为的类是很有意义的。你也可以使用这些方法来创建一般的可以包装其它对象的会话管理器。

                  class hello(object):

                          def __init__(self, text):

                                   self.text = text

                                   print self.text

                          def __enter__(self):

                                   self.text = "hello " + self.text    # add prefix

                                   print self.text

                                   return self                          # note: return an object

                          def __exit__(self,exc_type,exc_value,traceback):

                                   self.text = self.text + " i love u"          # add suffix

                  with hello("world") as myhello:

                          pass  

                  print(myhello.text)

                  输出结果:

                  world                #__init__的结果

                  hello world           #__enter__的结果

                  hello world I lov u       #__exit__的结果

                  当程序块中出现异常(exception)__exit__()的参数中exc_type, exc_value, traceback用于描述异常。我们可以根据这三个参数进行相应的处理。如果正常运行结束,这三个参数都是None

 

contextlib

Python标准库包括了一个叫作 contextlib 的模块,其包含了一个上下文管理器contextmanager,它是为了加强with语句,提供上下文机制的模块,它是通过Generator实现的。通过定义类以及写__enter____exit__来进行上下文管理虽然不难,但是很繁琐。contextlib中的contextmanager作为装饰器来提供一种针对函数级别的上下文管理机制。

        from contextlib import contextmanager
        @
contextmanager
       def
hello(text):
               text =
'hello'
+ text
              
print
text
              
yield
             
text = text+
' i love u'
             
print
text

       with hello("world"
):
              
print "world"

                  首先执行yield前的代码,然后调用with中间包含的代码,最后执行yield后面代码

 

PARAMIKO

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

sshclient

       用于连接远程服务器并执行基本命令

       import paramiko

        

       # 创建SSH对象

       ssh = paramiko.SSHClient()

       # 允许连接不在know_hosts文件中的主机

       ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

       # 连接服务器

       ssh.connect(hostname='192.168.137.2', port=22, username=’han’, password='123')

        

       # 执行命令

       stdin, stdout, stderr = ssh.exec_command('df')

       # 获取命令结果

       result = stdout.read()

        

       # 关闭连接

       ssh.close()

 

       sshclient 封装transport

       import paramiko

 

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

       transport.connect(username='wupeiqi', password='123')

 

       ssh = paramiko.SSHClient()

       ssh._transport = transport

 

       stdin, stdout, stderr = ssh.exec_command('df')

       print stdout.read()

 

       transport.close()

 

       基于公钥密钥连接:

       import paramiko

        

       private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')

        

       # 创建SSH对象

       ssh = paramiko.SSHClient()

       # 允许连接不在know_hosts文件中的主机

       ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

       # 连接服务器

       ssh.connect(hostname='xxx',port=22, username='wupeiqi',key=private_key)

        

       # 执行命令

       stdin, stdout, stderr = ssh.exec_command('df')

       # 获取命令结果

       result = stdout.read()

        

       # 关闭连接

       ssh.close()

 

       SSHClient 基于私钥封装 Transport

       import paramiko

 

       private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')

 

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

       transport.connect(username='wupeiqi', pkey=private_key)

 

       ssh = paramiko.SSHClient()

       ssh._transport = transport

 

       stdin, stdout, stderr = ssh.exec_command('df')

 

       transport.close()

 

       SFTPClient

              import paramiko

        

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

       transport.connect(username='wupeiqi',password='123')

        

       sftp = paramiko.SFTPClient.from_transport(transport)

       # location.py 上传至服务器 /tmp/test.py

       sftp.put('/tmp/location.py', '/tmp/test.py')

       # remove_path 下载到本地 local_path

       sftp.get('remove_path', 'local_path')

        

       transport.close()

 

       基于公钥密钥上传下载

       使用密码连接

       import paramiko

        

       private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')

        

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

       transport.connect(username='wupeiqi', pkey=private_key )

        

       sftp = paramiko.SFTPClient.from_transport(transport)

       # location.py 上传至服务器 /tmp/test.py

       sftp.put('/tmp/location.py', '/tmp/test.py')

       # remove_path 下载到本地 local_path

       sftp.get('remove_path', 'local_path')

        

       transport.close()

 

 

堡垒机

       wKioL1aZOZGCpIH2AAJ2csfkFF0514.png

 

堡垒机执行流程:

 

管理员为用户在服务器上创建账号(将公钥放置服务器,或者使用用户名密码)

用户登陆堡垒机,输入堡垒机用户名密码,显示当前用户管理的服务器列表

用户选择服务器,并自动登陆

执行操作并同时将用户操作记录

 

登录服务器代码

       tran = paramiko.Transport((hostname, port,))

tran.start_client()

default_path = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa')

key = paramiko.RSAKey.from_private_key_file(default_path)

tran.auth_publickey('wupeiqi', key)

 

# 打开一个通道

chan = tran.open_session()

# 获取一个终端

chan.get_pty()

# 激活器

chan.invoke_shell()

 

#########

# 利用sys.stdin,肆意妄为执行操作

# 用户在终端输入内容,并将内容发送至远程服务器

# 远程服务器执行命令,并将结果返回

# 用户终端显示内容

#########

 

chan.close()

tran.close()

 

中间代码块 1:普通模式,输入命令回车后将命令发给服务器

while True:

    # 监视用户输入和服务器返回数据

    # sys.stdin 处理用户输入

    # chan 是之前创建的通道,用于接收服务器返回信息

    readable, writeable, error = select.select([chan, sys.stdin, ],[],[],1)

    if chan in readable:

        try:

            x = chan.recv(1024)

            if len(x) == 0:

                print '\r\n*** EOF\r\n',

                break

            sys.stdout.write(x)

            sys.stdout.flush()

        except socket.timeout:

            pass

    if sys.stdin in readable:

        inp = sys.stdin.readline()

        chan.sendall(inp)

 

中间代码块 2每输入一个字符,都会发到服务器端sys.stdin.read(1)

# 获取原tty属性

oldtty = termios.tcgetattr(sys.stdin)

try:

    # tty设置新属性

    # 默认当前tty设备属性:

    #   输入一行回车,执行

    #   CTRL+C 进程退出,遇到特殊字符,特殊处理。

 

    # 这是为原始模式,不认识所有特殊符号

    # 放置特殊字符应用在当前终端,如此设置,将所有的用户输入均发送到远程服务器

    tty.setraw(sys.stdin.fileno())

    chan.settimeout(0.0)

 

    while True:

        # 监视用户输入远程服务器返回数据(socket

        # 阻塞,直到句柄可读

        r, w, e = select.select([chan, sys.stdin], [], [], 1)

        if chan in r:

            try:

                x = chan.recv(1024)

                if len(x) == 0:

                    print '\r\n*** EOF\r\n',

                    break

                sys.stdout.write(x)

                sys.stdout.flush()

            except socket.timeout:

                pass

        if sys.stdin in r:

            x = sys.stdin.read(1)

            if len(x) == 0:

                break

            chan.send(x)

 

finally:

    # 重新设置终端属性

    termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)

 

中间代码块 3

def windows_shell(chan):

    import threading

 

    sys.stdout.write("Line-buffered terminal emulation. Press F6 or ^Z to send EOF.\r\n\r\n")

 

    def writeall(sock):

        while True:

            data = sock.recv(256)

            if not data:

                sys.stdout.write('\r\n*** EOF ***\r\n\r\n')

                sys.stdout.flush()

                break

            sys.stdout.write(data)

            sys.stdout.flush()

 

    writer = threading.Thread(target=writeall, args=(chan,))

    writer.start()

 

    try:

        while True:

            d = sys.stdin.read(1)

            if not d:

                break

            chan.send(d)

    except EOFError:

        # user hit ^Z or F6

        pass    

             

注:密码验证 t.auth_password(username, pw)          

 

python mysql api

         插入数据

         import MySQLdb

         conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1234',db='mydb')

         cur = conn.cursor()

         reCount = cur.execute('insert into UserInfo(Name,Address) values(%s,%s)',('alex','usa'))

         conn.commit()

         cur.close()

         conn.close()

         print reCount

 

         批量插入

         li =[ ('alex','usa'), ('sb','usa'),  ]

         reCount = cur.executemany('insert into UserInfo(Name,Address) values(%s,%s)',li)

        

         取数据

         reCount = cur.execute('select * from UserInfo')

         print cur.fetchone()

         print cur.fetchone()   #取一条

         cur.scroll(-1,mode='relative')

         print cur.fetchone()

         print cur.fetchone()

         cur.scroll(0,mode='absolute')

         print cur.fetchmany(3)   #取多条

         print cur.fetchone(5)

         cur.close()

         conn.close()

         print reCount

 

         nRet = cur.fetchall()    #全部取出

 

reCount 为影响的行数

int(cur.lastrowid)  返回这个游标最后一个记录的主键ID

int(conn.insert_id()) 返回这个连接的最后一个记录的主键ID

    如果有多个游标,lastrowid不同,但conn.insert_id 相同,除非 conn也不同

 

 

你可能感兴趣的:(mysqldb,with,Lock,paramiko,RLock)