在阅读了前两章之后:
多多教Python:Python 基本功: 4. 读写文件zhuanlan.zhihu.com
多多教Python:Python 基本功: 5. 数据序列化zhuanlan.zhihu.com
我们手上已经有足够的工具来写一个完整的 Python 程序,而 __main__ 方法是进入 Python 世界的大门,所有的程序运行从这里开始。
这篇教程教大家写第一个完整的 Python 程序:读取,处理金融数据并且生成每日汇总报告。虽然代码不多,但是这个程序是一个非常有用的日常工具。
教程需求:
- Mac OS (Windows, Linux 会略有不同)
- 安装了 Python 3.0 版本以上, PyCharm
- 阅读了 多多教Python:Python 基本功: 4. 读写文件, Python 基本功: 5. 数据序列化
__main__ 开始 Python 程序
Python 程序是只在 Python 环境下,独立运行的一个进程,有管理自己的内存,I/O, 网络,计算资源等。如果你需要创建一个 Python 的脚本,任务,或者大型的项目,都需要一个或者以上独立的进程。而进程的开始,是从 main() 方法,在 Python 中 main() 方法可以被这么定义:
first_main.py, 第一个 main 方法
就像绿色箭头所指的,第七行我们通过这个语法定义了 main() 方法,并且在接下来的代码都是在 main() 方法内部所调用的。你会发现内容是 Python 基本功: 4. 读写文件 里教的如何从一个关于日期,价格的金融文件中读取数据,并且保存进字典,所以我们就不一行一行展开了,有兴趣的小伙伴可以回到前文再重温一遍。
在 PyCharm 中运行程序
现在我们写完了代码,让我们在 PyCharm 中尝试运行一下这个文件,还没有用过 PyCharm 的小伙伴可以参考: Python 基本功: 1. Hello world 里的用 PyCharm 创建 Hello World 项目的部分。
首先我们打开 PyCharm, 像前文一样创建一个 Pure Python (纯 Python) 的项目,这里项目叫 HelloWorld, 你也可以自己起名字。进入之后创建一个 python 文件叫 first_main.py, 并且把 abc _ date _ price.txt 文件放入这个文件夹,文件内容如下:
abc_date_price.txt -->
7/18/2019,9682.24
7/17/2019,9411.61
7/16/2019,10858.7
7/15/2019,10195.0
7/14/2019,11378.23
7/13/2019,11810.0
7/12/2019,11338.9
7/11/2019,12090.99
7/10/2019,12577.85 <-- end
现在我们在新文件 first_main.py 中,参考第一张图片写入我们第一个 main() 方法,然后保存文件。
现在我们按下 cntrl + 左shift + R, 或者像下图右击文件,点 Run 'first_main'
开始运行程序
随后我们会发现在 PyCharm 底下出现了程序打印出来的字典,然后退出 (Process finished with exit code 0)。这样我们的程序就结束了,虽然成功读取了数据,打印了出来,但是我们并没有完成处理数据和生成报告的部分,所以我们就来补充 __main__ 方法,见下面的代码:
# 计算高低价格,回报率
这里把字典里的数据做了运算处理,然后以 Json 的形式的报告保存下来。虽然用到了一些还没有讲到的 Python 内容包括字符串格式化 (string formatting),运算加载 (operator overload),迭代器 (iterator) 等,但是得益于 Python 语法的简洁易懂,我想这里大家都应该看明白了,我就讲其中2个方法:
- abc_dict.values() 表示获取字典里全部的数值,并且以“字典数值”的类来返还,但是你可以通过 list() 或者别的类转换方法来转换成其他的数据类型。
- "{:.2f}".format() 这个方法是把一个数值转换成格式化的字符串,这里代表着一个只有2位小数点的浮点(f 代表 float),虽然 ret_pcnt * 100 可能是很多位小数,但是在格式化之后只会出现2位小数,方便阅览。
再次运行程序之后,在同一个文件夹里,我们会发现一个新生成的文件叫 "abc_report.json", 我们打开会发现下面一串字符:
这是 Json 形式的报告,虽然在文本编辑器里看起来没有特别舒服,但是我们可以把内容黏贴到一个 Json 在线的解析器: Json 在线解析 网页中查看:
Json 解析完成的金融报告
因为在 Python 基本功: 5. 数据序列化 中所讲到的,网站和后台之间的数据传输很多用的 Json 序列化格式,当我们把数据Json化之后,网页也可以很轻松的读取数据并且进行美化和排版,这样可以通过浏览器直接做报告展示。
终端内运行 Python 程序
很多场景是我们写完了Python文件之后,需要直接在终端内执行,而不是通过像 PyCharm 这样的 IDE, 比如说在没有IDE安装的云端,你必须通过在终端执行命令来完成 Python 任务的运行,现在我们来看这样怎么操作。
(base) 192:HelloWorld xxx$ ./venv/bin/python3.7 first_main.py
没错,就一行! 首先你进入到文件所在的文件夹,然后直接输入 ./venv/bin/python3.7 + 带有 __main__ 方法的文件就可以,随后你就会看到终端打印出来的运行信息,然后程序退出,生成了一个新的 abc_report.json。这里为什么不直接用 Python3 而用 "./venv/bin" 文件夹下的 python3.7 呢?是因为 PyCharm 帮我们创建了一个
虚拟环境,当然我们自己也可以创建,后文会讲到,而这个虚拟环境的可执行 Python3.7 有自己独立的库环境,从安全角度可以让程序完全的隔离开来。
像 多多教Python:Python 基本功: 1. Hello world 提到的,Python 程序会依附在终端之下,如果你关闭了终端,那程序就停止了。现在假设我们在云端,并且需要在终端关闭了之后,Python 程序能够完全独立的运营下去,那我们就输入:
(base) 192:HelloWorld xxx$ nohup ./venv/bin/python3.7 first_main.py &
[1] 3993
(base) 192:HelloWorld xxx$ appending output to nohup.out
你会看到在执行了第一行的命令之后,出现了一个数字 3993, 这个数字就是在操作系统内核下的独立的 Python 进程ID, 随后出现了 'appending outout to nohup.out', 表示原本在终端内打印出来的内容将导入到 nohup.out 这个文件中。我们会发现除了生成出来的报告 'abc_report.json' 之外,还生成了一个 nohup.out 文件,这个文件里的内容就是原本在终端打印出来的输出。
读取 __main__ 参数
很多时候当我们启动一个程序时,会传入不同的参数让程序做不同的事情。比如在这篇文章的例子中,我们想要每天都生成一个文件,为了不覆盖之前的文件,我们给文件名加一个后缀,就是当天的日期,那该如何实现呢?
其实非常简单,首先我们调用 sys 模块,这是一个 Python 自带的系统子库,帮助和终端,操作系统进行互动。在进入 __main__ 之后,我们通过 sys.argv,sys 模块中的一个变量,这个变量保存了传入main() 的参数,来查看有几个参数。如果 len(),Python 自带的查看数据组长度的方法, 返回的是大于一,那就提取第二个参数来作为文件日期后缀,否则后缀为空。这里如果看不明白 if...else... 逻辑后文会讲。
那为什么这里是读取第二个参数,而不是第一个呢?因为第一个参数永远是带有 __main__ 方法的文件名,而我们传入的第一个参数在 sys.argv 里面就保存在第二个位置,现在我们来尝试运行:
(base) 192:HelloWorld xxx$ ./venv/bin/python3.7 first_main.py 20191021
我们传入了一个日期参数: 20191021, 然后运行程序,我们会发现生成的文件就有了 20191021这个后缀,所以之后每天我们运行同一个程序,但是传入当天的日期参数,就可以得到一个不同的文件,不用担心名称重复的问题。
小结
如果你看到这里,那恭喜你的第一个完整的 Python 程序就做好了。当然这篇文章如果深挖的话有很多衍生内容,包括计算机的进程,内核后台管理,终端输入/输出,动态读参这些。虽然后面的教程都会涉及。但是有兴趣的小伙伴可以先去看一下下面的链接:
一个外部的终端基础操作文章:
Linux终端基础www.jianshu.com
一个动态读参的 Python 库:
argparsepypi.org
Python 进程,多进程模块:
17.2. multiprocessing - Process-based parallelism - Python 3.4.10 documentationdocs.python.org