Linux 平台下 Python 脚本编程入门(二)

简介:

本篇中,我们会讨论控制流(根据用户输入的信息、计算的结果,或者一个变量的当前值选择不同的动作行为)和循环(自动重复执行任务),接着应用我们目前所学东西来编写一个简单的 shell 脚本,这个脚本会显示操作系统类型、主机名、内核版本、版本号和机器硬件架构。

这个例子尽管很基础,但是会帮助我们证明,比起使用一般的 bash 工具,我们通过发挥 Python 面向对象的特性来编写 shell 脚本会更简单些。

换句话说,我们想从这里出发:

 
  1. # uname -snrvm

检查 Linux 的主机名

检查 Linux 的主机名

用 Python 脚本来检查 Linux 的主机名

用 Python 脚本来检查 Linux 的主机名

或者

用脚本检查 Linux 系统信息

用脚本检查 Linux 系统信息

看着不错,不是吗?那我们就挽起袖子,开干吧。

Python 中的控制流

如我们刚说那样,控制流允许我们根据一个给定的条件,选择不同的输出结果。在 Python 中最简单的实现就是一个 if/else 语句。

基本语法是这样的:

 
  1. if 条件:
  2. # 动作 1
  3. else:
  4. # 动作 2

当“条件”求值为真(true),下面的代码块就会被执行(# 动作 1代表的部分)。否则,else 下面的代码就会运行。 “条件”可以是任何表达式,只要可以求得值为真或者假。

举个例子:

  1. 1 < 3 # 真
  2. firstName == "Gabriel" # 对 firstName 为 Gabriel 的人是真,对其他不叫 Gabriel 的人为假
  • 在第一个例子中,我们比较了两个值,判断 1 是否小于 3。
  • 在第二个例子中,我们比较了 firstName(一个变量)与字符串 “Gabriel”,看在当前执行的位置,firstName 的值是否等于该字符串。
  • 条件和 else 表达式都必须跟着一个冒号(:)。
  • 缩进在 Python 中非常重要。同样缩进下的行被认为是相同的代码块。

请注意,if/else 表达式只是 Python 中许多控制流工具的一个而已。我们先在这里了解以下,后面会用在我们的脚本中。你可以在官方文档中学到更多工具。

Python 中的循环

简单来说,一个循环就是一组指令或者表达式序列,可以按顺序一直执行,只要条件为真,或者对列表里每个项目执行一一次。

Python 中最简单的循环,就是用 for 循环迭代一个给定列表的元素,或者对一个字符串从第一个字符开始到执行到最后一个字符结束。

基本语句:

 
  1. for x in example:
  2. # do this

这里的 example 可以是一个列表或者一个字符串。如果是列表,变量 x 就代表列表中每个元素;如果是字符串,x 就代表字符串中每个字符。

 
  1. >>> rockBands = []
  2. >>> rockBands.append("Roxette")
  3. >>> rockBands.append("Guns N' Roses")
  4. >>> rockBands.append("U2")
  5. >>> for x in rockBands:
  6. print(x)
  7. >>> firstName = "Gabriel"
  8. >>> for x in firstName:
  9. print(x)

上面例子的输出如下图所示:

学习 Python 中的循环

学习 Python 中的循环

Python 模块

很明显,必须有个办法将一系列的 Python 指令和表达式保存到文件里,然后在需要的时候取出来。

准确来说模块就是这样的。比如,os 模块提供了一个到操作系统的底层的接口,可以允许我们做许多通常在命令行下执行的操作。

没错,os 模块包含了许多可以用来调用的方法和属性,就如我们之前文章里讲解的那样。不过,我们需要使用import 关键词导入(或者叫包含)模块到运行环境里来:

 
  1. >>> import os

我们来打印出当前的工作目录:

 
  1. >>> os.getcwd()

学习 Python 模块

学习 Python 模块

现在,让我们把这些结合在一起(包括之前文章里讨论的概念),编写需要的脚本。

Python 脚本

以一段声明文字开始一个脚本是个不错的想法,它可以表明脚本的目的、发布所依据的许可证,以及一个列出做出的修改的修订历史。尽管这主要是个人喜好,但这会让我们的工作看起来比较专业。

这里有个脚本,可以输出这篇文章最前面展示的那样。脚本做了大量的注释,可以让大家可以理解发生了什么。

在进行下一步之前,花点时间来理解它。注意,我们是如何使用一个 if/else 结构,判断每个字段标题的长度是否比字段本身的值还大。

基于比较结果,我们用空字符去填充一个字段标题和下一个之间的空格。同时,我们使用一定数量的短线作为字段标题与其值之间的分割符。

 
  1. #!/usr/bin/python3
  2. # 如果你没有安装 Python 3 ,那么修改这一行为 #!/usr/bin/python
  3. # Script name: uname.py
  4. # Purpose: Illustrate Python OOP capabilities to write shell scripts more easily
  5. # License: GPL v3 (http://www.gnu.org/licenses/gpl.html)
  6. # Copyright (C) 2016 Gabriel Alejandro Cánepa
  7. # Facebook / Skype / G+ / Twitter / Github: gacanepa
  8. # Email: gacanepa (at) gmail (dot) com
  9. # This program is free software: you can redistribute it and/or modify
  10. # it under the terms of the GNU General Public License as published by
  11. # the Free Software Foundation, either version 3 of the License, or
  12. # (at your option) any later version.
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU General Public License for more details.
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program. If not, see .
  19. # REVISION HISTORY
  20. # DATE VERSION AUTHOR CHANGE DESCRIPTION
  21. # ---------- ------- --------------
  22. # 2016-05-28 1.0 Gabriel Cánepa Initial version
  23. ### 导入 os 模块
  24. import os
  25. ### 将 os.uname() 的输出赋值给 systemInfo 变量
  26. ### os.uname() 会返回五个字符串元组(sysname, nodename, release, version, machine)
  27. ### 参见文档:https://docs.python.org/3.2/library/os.html#module-os
  28. systemInfo = os.uname()
  29. ### 这是一个固定的数组,用于描述脚本输出的字段标题
  30. headers = ["Operating system","Hostname","Release","Version","Machine"]
  31. ### 初始化索引值,用于定义每一步迭代中
  32. ### systemInfo 和字段标题的索引
  33. index = 0
  34. ### 字段标题变量的初始值
  35. caption = ""
  36. ### 值变量的初始值
  37. values = ""
  38. ### 分隔线变量的初始值
  39. separators = ""
  40. ### 开始循环
  41. for item in systemInfo:
  42. if len(item) < len(headers[index]):
  43. ### 一个包含横线的字符串,横线长度等于item[index] 或 headers[index]
  44. ### 要重复一个字符,用引号圈起来并用星号(*)乘以所需的重复次数
  45. separators = separators + "-" * len(headers[index]) + " "
  46. caption = caption + headers[index] + " "
  47. values = values + systemInfo[index] + " " * (len(headers[index]) - len(item)) + " "
  48. else:
  49. separators = separators + "-" * len(item) + " "
  50. caption = caption + headers[index] + " " * (len(item) - len(headers[index]) + 1)
  51. values = values + item + " "
  52. ### 索引加 1
  53. index = index + 1
  54. ### 终止循环
  55. ### 输出转换为大写的变量(字段标题)名
  56. print(caption.upper())
  57. ### 输出分隔线
  58. print(separators)
  59. # 输出值(systemInfo 中的项目)
  60. print(values)
  61. ### 步骤:
  62. ### 1) 保持该脚本为 uname.py (或任何你想要的名字)
  63. ### 并通过如下命令给其执行权限:
  64. ### chmod +x uname.py
  65. ### 2) 执行它;
  66. ### ./uname.py

如果你已经按照上述描述将上面的脚本保存到一个文件里,并给文件增加了执行权限,那么运行它:

 
  1. # chmod +x uname.py
  2. # ./uname.py

如果试图运行脚本时你得到了如下的错误:

 
  1. -bash: ./uname.py: /usr/bin/python3: bad interpreter: No such file or directory

这意味着你没有安装 Python3。如果那样的话,你要么安装 Python3 的包,要么替换解释器那行(如果如之前文章里概述的那样,跟着下面的步骤去更新 Python 执行文件的软连接,要特别注意并且非常小心):

 
  1. #!/usr/bin/python3

 
  1. #!/usr/bin/python

这样会通过使用已经安装好的 Python 2 去执行该脚本。

注意:该脚本在 Python 2.x 与 Pyton 3.x 上都测试成功过了。

尽管比较粗糙,你可以认为该脚本就是一个 Python 模块。这意味着你可以在 IDLE 中打开它(File → Open… → Select file):

在 IDLE 中打开 Python

在 IDLE 中打开 Python

一个包含有文件内容的新窗口就会打开。然后执行 Run → Run module(或者按 F5)。脚本的输出就会在原始的 Shell 里显示出来:

执行 Python 脚本

执行 Python 脚本

如果你想纯粹用 bash 写一个脚本,也获得同样的结果,你可能需要结合使用 awksed,并且借助复杂的方法来存储与获得列表中的元素(不要忘了使用 tr 命令将小写字母转为大写)。

另外,在所有的 Linux 系统版本中都至少集成了一个 Python 版本(2.x 或者 3.x,或者两者都有)。你还需要依赖 shell 去完成同样的目标吗?那样你可能需要为不同的 shell 编写不同的版本。

这里演示了面向对象编程的特性,它会成为一个系统管理员得力的助手。

注意:你可以在我的 Github 仓库里获得 这个 python 脚本(或者其他的)。

总结

这篇文章里,我们讲解了 Python 中控制流、循环/迭代、和模块的概念。我们也演示了如何利用 Python 中面向对象编程的方法和属性来简化复杂的 shell 脚本。

原文发布时间为:2016-08-19

本文来自云栖社区合作伙伴“Linux中国”

相关文章
|
8天前
|
安全 Java 数据处理
Python网络编程基础(Socket编程)多线程/多进程服务器编程
【4月更文挑战第11天】在网络编程中,随着客户端数量的增加,服务器的处理能力成为了一个重要的考量因素。为了处理多个客户端的并发请求,我们通常需要采用多线程或多进程的方式。在本章中,我们将探讨多线程/多进程服务器编程的概念,并通过一个多线程服务器的示例来演示其实现。
|
8天前
|
程序员 开发者 Python
Python网络编程基础(Socket编程) 错误处理和异常处理的最佳实践
【4月更文挑战第11天】在网络编程中,错误处理和异常管理不仅是为了程序的健壮性,也是为了提供清晰的用户反馈以及优雅的故障恢复。在前面的章节中,我们讨论了如何使用`try-except`语句来处理网络错误。现在,我们将深入探讨错误处理和异常处理的最佳实践。
|
11天前
|
缓存 监控 Python
解密Python中的装饰器:优雅而强大的编程利器
Python中的装饰器是一种强大而又优雅的编程工具,它能够在不改变原有代码结构的情况下,为函数或类添加新的功能和行为。本文将深入解析Python装饰器的原理、用法和实际应用,帮助读者更好地理解和利用这一技术,提升代码的可维护性和可扩展性。
|
17天前
|
Linux Shell
Linux手动清理Linux脚本日志定时清理日志和log文件执行表达式
Linux手动清理Linux脚本日志定时清理日志和log文件执行表达式
71 1
|
1天前
|
API Python
Python模块化编程:面试题深度解析
【4月更文挑战第14天】了解Python模块化编程对于构建大型项目至关重要,它涉及代码组织、复用和维护。本文深入探讨了模块、包、导入机制、命名空间和作用域等基础概念,并列举了面试中常见的模块导入混乱、不适当星号导入等问题,强调了避免循环依赖、合理使用`__init__.py`以及理解模块作用域的重要性。掌握这些知识将有助于在面试中自信应对模块化编程的相关挑战。
12 0
|
2天前
|
Python
python面型对象编程进阶(继承、多态、私有化、异常捕获、类属性和类方法)(上)
python面型对象编程进阶(继承、多态、私有化、异常捕获、类属性和类方法)(上)
22 0
|
7天前
|
JavaScript 搜索推荐 前端开发
音乐发现平台:借助Python和Vue构建个性化音乐推荐系统
【4月更文挑战第11天】本文介绍了如何使用Python和Vue.js构建个性化音乐推荐系统。首先确保安装Python、Node.js、数据库系统和Git。后端可选择Flask或Django搭建RESTful API,处理歌曲数据。前端利用Vue.js创建用户界面,结合Vue CLI、Vuex和Vue Router实现功能丰富的SPA。通过Vuex管理状态,Axios与后端通信。这种前后端分离的架构利于协作和系统扩展,助力打造定制化音乐体验。
|
9天前
|
JSON 测试技术 持续交付
自动化测试与脚本编写:Python实践指南
【4月更文挑战第9天】本文探讨了Python在自动化测试中的应用,强调其作为热门选择的原因。Python拥有丰富的测试框架(如unittest、pytest、nose)以支持自动化测试,简化测试用例的编写与维护。示例展示了使用unittest进行单元测试的基本步骤。此外,Python还适用于集成测试、系统测试等,提供模拟外部系统行为的工具。在脚本编写实践中,Python的灵活语法和强大库(如os、shutil、sqlite3、json)助力执行复杂测试任务。同时,Python支持并发、分布式执行及与Jenkins、Travis CI等持续集成工具的集成,提升测试效率和质量。
|
16天前
|
存储 监控 异构计算
【Python】GPU内存监控脚本
【Python】GPU内存监控脚本
|
16天前
|
Ubuntu Unix Linux
【Linux/Ubuntu】Linux/Ubuntu运行python脚本
【Linux/Ubuntu】Linux/Ubuntu运行python脚本