目录 | 上一节 (3.4 模块) | 下一节 (3.6 设计讨论)

3.5 主模块

本节介绍主程序(主模块)的概念

主函数

在许多编程语言中,存在一个主函数或者主方法的概念。

  1. // c / c++
  2. int main(int argc, char *argv[]) {
  3. ...
  4. }
  1. // java
  2. class myprog {
  3. public static void main(String args[]) {
  4. ...
  5. }
  6. }

这是启动应用程序时执行的第一个函数。

Python 主模块

Python 没有主函数(main function)或主方法(main method)。相反,Python 有一个主模块(main

module)。主模块是第一个运行的源文件。

  1. bash % python3 prog.py
  2. ...

在应用程序启动时,提供给解释器的任何文件都将成为主模块。名字并不重要。

__main__ 检查

对于作为主脚本运行的模块,使用此约定(译注:__main__ 检查)是标准做法。

  1. # prog.py
  2. ...
  3. if __name__ == '__main__':
  4. # Running as the main program ...
  5. statements
  6. ...

if 里面的语句称为主程序( main program)。

主程序与库导入

任何 Python 文件都可以作为主程序运行,或者作为一个库(译注:library,在 Python 中 library 既可以指模块 module,也可以指包 package),导入后运行。

  1. bash % python3 prog.py # Running as main
  1. import prog # Running as library import

在这两种情况下,__name__ 都是模块的名称(译注:prog)。然而,如果作为主程序运行,__name__ 只能被设置为 __main__

通常,我们不希望主程序中的语句在库导入的时候执行。所以,通常在代码中包含一个 if- 检查,判断当前文件是否是主程序(译注:如果当前程序不是主程序,则 if __name__ == '__main__': 里面的语句不执行)。

  1. if __name__ == '__main__':
  2. # Does not execute if loaded with import ...

程序模板

这里有一个用于编写 Python 程序的通用模板:

  1. # prog.py
  2. # Import statements (libraries)
  3. import modules
  4. # Functions
  5. def spam():
  6. ...
  7. def blah():
  8. ...
  9. # Main function
  10. def main():
  11. ...
  12. if __name__ == '__main__':
  13. main()

命令行工具

Python 通常在命令行工具中使用:

  1. bash % python3 report.py portfolio.csv prices.csv

这意味着脚本在 shell 或者 终端(terminal)执行。通常用于自动化,后台任务等。

命令行参数

命令行参数是一个文本字符串列表。

  1. bash % python3 report.py portfolio.csv prices.csv

该文本字符串列表可以在 sys.argv 中找到。

  1. # In the previous bash command
  2. sys.argv # ['report.py, 'portfolio.csv', 'prices.csv']

这里有一个处理参数的简单示例:

  1. import sys
  2. if len(sys.argv) != 3:
  3. raise SystemExit(f'Usage: {sys.argv[0]} ' 'portfile pricefile')
  4. portfile = sys.argv[1]
  5. pricefile = sys.argv[2]
  6. ...

标准 I/O

标准输入/输出(或者stdio)是和普通文件使用相同工作方式的文件。

  1. sys.stdout
  2. sys.stderr
  3. sys.stdin

默认情况下,打印定向到 sys.stdout 文件。输入是从 sys.stdin 文件读取。回溯和错误定向到 sys.stderr 文件。

请注意,标准输入/输出(stdio)可以连接到终端(terminals),文件(files),管道(pipes)等。

  1. bash % python3 prog.py > results.txt
  2. # or
  3. bash % cmd1 | python3 prog.py | cmd2

环境变量

环境变量在 shell 中设置。

  1. bash % setenv NAME dave
  2. bash % setenv RSH ssh
  3. bash % python3 prog.py

os.environ 是包含这些值的字典。

  1. import os
  2. name = os.environ['NAME'] # 'dave'

更改会反映在程序随后启动的任何子进程中。

程序退出

通过异常处理程序退出。

  1. raise SystemExit
  2. raise SystemExit(exitcode)
  3. raise SystemExit('Informative message')

其它方式。

  1. import sys
  2. sys.exit(exitcode)

非零(non-zero )退出码表示错误。

#!

在 Unix 系统中,#! 行指定某个路径下的 Python 解释器来执行该脚本(译注:#! 称为 Shebang 或者 hashbang,因为 # 号通常称为 hash 或者 sharp,而 ! 号则常常称为 bang)。将以下内容添加到脚本文件的第一行。

  1. #!/usr/bin/env python3
  2. # prog.py
  3. ...

(译注:#!/usr/bin/env python3 的意思——到 Unix 系统 env 所包含的全部环境变量中寻找 Python3 解释器,并使用 Python3 解释器执行该脚本)

执行脚本需要脚本具有可执行权限。

  1. bash % chmod +x prog.py
  2. # Then you can execute
  3. bash % prog.py
  4. ... output ...

注意:Windows 系统上的 Python 启动器也会寻找 #! 行以指示语言版本。

脚本模板

最后,这里有一个通用代码模板,用于将 Python 程序作为命令行脚本运行:

  1. #!/usr/bin/env python3
  2. # prog.py
  3. # Import statements (libraries)
  4. import modules
  5. # Functions
  6. def spam():
  7. ...
  8. def blah():
  9. ...
  10. # Main function
  11. def main(argv):
  12. # Parse command line args, environment, etc.
  13. ...
  14. if __name__ == '__main__':
  15. import sys
  16. main(sys.argv)

练习

练习 3.15:main() 函数

report.py 文件中添加一个 main() 函数,该函数接受命令行选项列表,并生成与以前相同的输出。修改后,应该能够像下面这样交互地运行它:

  1. >>> import report
  2. >>> report.main(['report.py', 'Data/portfolio.csv', 'Data/prices.csv'])
  3. Name Shares Price Change
  4. ---------- ---------- ---------- ----------
  5. AA 100 9.22 -22.98
  6. IBM 50 106.28 15.18
  7. CAT 150 35.46 -47.98
  8. MSFT 200 20.89 -30.34
  9. GE 95 13.48 -26.89
  10. MSFT 50 20.89 -44.21
  11. IBM 100 106.28 35.84
  12. >>>

请修改 pcost.py 文件,添加一个类似的 main() 函数。

  1. >>> import pcost
  2. >>> pcost.main(['pcost.py', 'Data/portfolio.csv'])
  3. Total cost: 44671.15
  4. >>>

练习 3.16:编写脚本

请修改 report.pypcost.py 程序,以便它们在命令行上可以作为脚本执行:

  1. bash $ python3 report.py Data/portfolio.csv Data/prices.csv
  2. Name Shares Price Change
  3. ---------- ---------- ---------- ----------
  4. AA 100 9.22 -22.98
  5. IBM 50 106.28 15.18
  6. CAT 150 35.46 -47.98
  7. MSFT 200 20.89 -30.34
  8. GE 95 13.48 -26.89
  9. MSFT 50 20.89 -44.21
  10. IBM 100 106.28 35.84
  11. bash $ python3 pcost.py Data/portfolio.csv
  12. Total cost: 44671.15

目录 | 上一节 (3.4 模块) | 下一节 (3.6 设计讨论)

注:完整翻译见 https://github.com/codists/practical-python-zh

翻译:《实用的Python编程》03_05_Main_module的更多相关文章

  1. 翻译:《实用的Python编程》InstructorNotes

    实用的 Python 编程--讲师说明 作者:戴维·比兹利(David Beazley) 概述 对于如何使用我的课程"实用的 Python 编程"进行教学的问题,本文档提供一些通用 ...

  2. 翻译:《实用的Python编程》README

    欢迎光临 大约 25 年前,当我第一次学习 Python 时,发现 Python 竟然可以被高效地应用到各种混乱的工作项目上,我立即被震惊了.15 年前,我自己也将这种乐趣教授给别人.教学的结果就是本 ...

  3. 翻译:《实用的Python编程》05_02_Classes_encapsulation

    目录 | 上一节 (5.1 再谈字典) | 下一节 (6 生成器) 5.2 类和封装 创建类时,通常会尝试将类的内部细节进行封装.本节介绍 Python 编程中有关封装的习惯用法(包括私有变量和私有属 ...

  4. 翻译:《实用的Python编程》04_02_Inheritance

    目录 | 上一节 (4.1 类) | 下一节 (4.3 特殊方法) 4.2 继承 继承(inheritance)是编写可扩展程序程序的常用手段.本节对继承的思想(idea)进行探讨. 简介 继承用于特 ...

  5. 翻译:《实用的Python编程》01_02_Hello_world

    目录 | 上一节 (1.1 Python) | 下一节 (1.3 数字) 1.2 第一个程序 本节讨论有关如何创建一个程序.运行解释器和调试的基础知识. 运行 Python Python 程序始终在解 ...

  6. 翻译:《实用的Python编程》03_03_Error_checking

    目录 | 上一节 (3.2 深入函数) | 下一节 (3.4 模块) 3.3 错误检查 虽然前面已经介绍了异常,但本节补充一些有关错误检查和异常处理的其它细节. 程序是如何运行失败的 Python 不 ...

  7. 翻译:《实用的Python编程》03_04_Modules

    目录 | 上一节 (3.3 错误检查) | 下一节 (3.5 主模块) 3.4 模块 本节介绍模块的概念以及如何使用跨多个文件的函数. 模块和导入 任何一个 Python 源文件都是一个模块. # f ...

  8. 翻译:《实用的Python编程》04_01_Class

    目录 | 上一节 (3.6 设计讨论) | 下一节 (4.2 继承) 4.1 类 本节介绍 class 语句以及创建新对象的方式. 面向对象编程(OOP) 面向对象编程是一种将代码组织成对象集合的编程 ...

  9. 翻译:《实用的Python编程》05_00_Overview

    目录 | 上一节 (4 类和对象) | 下一节 (6 生成器) 5. Python 对象的内部工作原理 本节介绍 Python 对象的内部工作原理.来自其它语言的程序员通常会发现 Python 的类概 ...

随机推荐

  1. codeforces251A. Points on Line

    Little Petya likes points a lot. Recently his mom has presented him n points lying on the line OX. N ...

  2. Codeforces Round #653 (Div. 3) C. Move Brackets

    题意/题解:经典括号匹配题目,不多说了. 代码: int t; int n; string s; int cnt; int main() { ios::sync_with_stdio(false);c ...

  3. [已完成+附代码]CS:APP:Lab6-ShellLab

    由于我的第五个实验的partB部分一直出问题.而且修了好久没解决先不管了 这个实验建议一定要认真读完csapp全书的第八章.不然可能会毫无思路.千万不要上来直接做. 0. 环境配置和实验下载 利用do ...

  4. 力扣567.字符串的排列—C语言实现

    题目 来源:力扣(LeetCode)

  5. Leetcode(105)-从前序与中序遍历序列构造二叉树

    根据一棵树的前序遍历与中序遍历构造二叉树. 注意:你可以假设树中没有重复的元素. 例如,给出 前序遍历 preorder = [3,9,20,15,7] 中序遍历 inorder = [9,3,15, ...

  6. Web 安全漏洞 All In One

    Web 安全漏洞 All In One Web 安全 & 漏洞 输入输出验证不充分 SQL 注入 XSS self-XSS CSRF 目录穿越 文件上传 代码注入 命令注入 信息漏洞 暴力破解 ...

  7. TypeScript Interface vs Types All In One

    TypeScript Interface vs Types All In One TypeScript https://www.typescriptlang.org/docs/handbook/adv ...

  8. redux 中间件 redux-saga 使用教程

    redux 中间件 redux-saga 使用教程 redux middleware refs https://redux-saga.js.org/docs/ExternalResources.htm ...

  9. shit mint-ui & navbar click event bug

    shit mint-ui & navbar click event bug # Vue 2.0 npm install mint-ui -S // 引入全部组件 import Vue from ...

  10. dark theme website

    dark theme website css var dark theme prefers-color-scheme https://developer.mozilla.org/en-US/docs/ ...