如何编写优雅的代码?

  1.消除硬编码

  第一个就是它有硬编码的情况,什么是硬编码,什么是硬编码就是说在代码里面,你用的一些变量它是写死的,比如说我们刚才调用connect APId的时候它的,ip地址端口用户名和密码都是我们写死的,什么192.168.3.106,用户名,密码,如果它的对端的这个端口它变了,或者说是密码用户名一般不会变。它的密码改变我们是不是要去修改代码,如果在实际工作中这样是非常不方便的,而且是有一定风险的,修改代码就意味着它可能是bug产生的边缘。所以说我们最好把这个可配置的代码,和变量分离开来。就是说消除硬编码的一个办法就是让它可配置。

  2.异常捕捉

  其次就是异常的捕捉,我们可以看到刚开始我们想列了,那个设置hot key机制时候,它调用connect方法,就抛出来一个sshaexception这个异常,但是我们并没有对它进行处理。这样的话就会在 实际的工作中它就非常的不好,甚至是有一些风险,因为不捕获这个异常的话,可能你的代码,就没办法在执行下去了,然后你写了这个软件可能就当掉了实际生产环境下,是一个非常严重的问题。

  3.封装

  另外就是进行一下封装,我们看到Paramiko它是对这个,它其实就是对ssh协议的一个封装,然而我们在实际的使用Paramiko的过程中,可以针对自己项目的需要。对它进行二次封装,就是说我封装成我们大家,一起,团队的人它更方便的使用它,甚至它可以不知道Paramiko这个的存在,而调用你封装的接口。来进行一个更方便的操作。

  那我们就看实际的过程中我们是怎样来解决这几个问题的,首先就是消除硬编码的问题,我们引入另外一个ConfigParser这个库,ConfigParser就是可以把这个配置很方便的读进来。

  config = ConfigParser.ConfigParser()

  然后它有一个readAPI就是读取文件。

  那现在我们就一起来建立一个文件,叫做config.ini

  [ssh]

  host=192.168.3.105

  port=22

  usr=allen

  pwd=123

  timeout=1.0

  然后我们read这个config.ini

  config.read(‘config.ini’)

  那么这些硬编码的地方,就可以换成对应的配置

  client.connect(hostname= config.get(‘ssh’,’host’), port= config.getint(‘ssh’,’ port’), username= config.get(‘ssh’,’ username’), password= config.get(‘ssh’,’ password’), timeout= config.getfloat(‘ssh’,’ timeout’))

  我们可以来运行看一下

  这样我们把这些变量给替换成用这个配置来解析出来它实际的值。我们就是用这个ConfigParser来完成的,现在它运行的是非常的好,然后我们就把这些实际的参数给用配置给它隐藏起来,如果将来我们配置一旦更改的时候我们只需要更改这个config.ini就可以,然后我们来看一下,如何进行异常的捕获。

  首先这个connect它会抛出这个异常的时候我们其实就应该用Pythontry来捕获它,然后用这个except Exception,e:可以把异常给打印出来。

  try:

  self.client.connect(hostname=self.host, port=self.port, username=self.usr, password=self.pwd, timeout=self.timeout)

  return True

  except Exception,e:

  print e

  这个时候呢一旦开启的时候我们记得要把它给close掉。避免造成资源的浪费

  self.client.connect(hostname=self.host, port=self.port, username=self.usr, password=self.pwd, timeout=self.timeout)

  return True

  except Exception,e:

  print 'caught ', e

  try:

  self.client.close()

  return False

  except:

  pass

  其实这样的话就把这个,简单的看一下异常的捕获,其实这个地方抛出捕获的时候我们就在这把它给捕获了,其实这个exec_command它也是会抛出异常。

  接下来我们就对它进行一个封装,如何封装,封装它是一个面向对象的一个特点,就会面向对象方法的一个特点,所以说我们把一些细节给隐藏起来,怎么隐藏呢,就是通过类。

  我们可以新建一个ParamikoClient这个类。

  class ParamikoClient:

  然后其实我们在它的初始化函数中就可以把config这个文件名给传进来。

  def __init__(self, ini_file):

  然后就可以进行一些初始化的工作,这个config要变成main自身的变量,这个Client也是变成它的一个成员,这个类的对象的一个成员。

  self. config= ConfigParser. ConfigParser ()

  self. Config. read(' config.ini ')

  self. Client= paramiko.SSHClient()

  self. Client= set_missing_host_key_policy(paramiko.AutoAddPolicy())

  然后我们还可以,定义它的connect方法,connect方法的时候就可以把这部分全部,拷贝过来。

  self.client.connect(hostname=self.host, port=self.port, username=self.usr, password=self.pwd, timeout=self.timeout)

  return True

  except Exception,e:

  print 'caught ', e

  try:

  self.client.close()

  return False

  except:

  pass

  然后最终这样就可以最后我们在封装一个如何执行命令的

  def run_command(self, cmd_str):

  stdin, stdout, stderr = self.client.exec_command(cmd_str)

  for line in stdout:

  print line

  这样一个类我么我们就做好了我们在用这个类来建立一个ParamikoClient

  client = ParamikoClient('config.ini')

  我们调用它的connect方法来接,

  client.connect()

  然后

  client.run_command('date')

  它把直接就把这个指令结果输出来了,我们还可以运行一下刚才输的查询远程机器的这个内存信息的指令。

  client = ParamikoClient('config.ini')

  client.connect()

  client.run_command('cat/proc/meminfo')

  我们这样就看到到了这个从它编码,到进行一个更优雅实现的这么一个过程。

  其实还有一个跟好的做法就是把这个ParamikoClient这个类单独放到一个文件里面,封装性会更好。

 

原文链接:http://www.maiziedu.com/wiki/frame/query/

posted @ 2016-11-07 11:35  程序猿终结者  阅读(2724)  评论(0编辑  收藏  举报