在终端执行 Python 代码的 6 种方式!

简介: 在终端执行 Python 代码的 6 种方式!

为了我们推出的 VS Code 的 Python 插件 [1],我写了一个简单的脚本来生成变更日志 [2](类似于Towncrier [3],但简单些,支持 Markdown,符合我们的需求)。在发布过程中,有一个步骤是运行python news ,它会将 Python 指向我们代码中的"news"目录。

前几天,一位合作者问这是如何工作的,似乎我们团队中的每个人都知道如何使用-m ?(请参阅我的有关带 -m 使用 pip 的文章 [4],了解原因)(译注:关于此话题,我也写过一篇更为详细的文章 )

这使我意识到其他人可能不知道有五花八门的方法可以将 Python 指向要执行的代码,因此有了这篇文章。

阿里云服务器1核2G低至82元/年,阿里云官活动网址:https://dashi.aliyun.com/site/yun/aliyun 可以用20代金券,即102-20=82。

1、通过标准输入和管道
因为如何用管道传东西给一个进程是属于 shell 的内容,我不打算深入解释。毋庸置疑,你可以将代码传递到 Python 中。

管道传内容给 python
echo "print('hi')" | python
如果将文件重定向到 Python,这显然也可以。

申请阿里云服务时,可以使用2000元阿里云代金券,阿里云官网领取网址:https://dashi.aliyun.com/site/yun/youhui

重定向一个文件给 python
python < spam.py
归功于 Python 的 UNIX 传统,这些都不太令人感到意外。

2、通过-c 指定的字符串
如果你只需要快速地检查某些内容,则可以在命令行中将代码作为字符串传递。

使用 python 的 -c 参数
python -c "print('hi')"
当需要检查仅一行或两行代码时,我个人会使用它,而不是启动 REPL(译注:Read Eval Print Loop,即交互式解释器,例如在 windows 控制台中输入python, 就会进入交互式解释器。-c 参数用法可以省去进入解释器界面的过程) 。

3、文件的路径
最众所周知的传代码给 python 的方法很可能是通过文件路径。

指定 python 的文件路径
python spam.py
要实现这一点的关键是将包含该文件的目录放到sys.path 里。这样你的所有导入都可以继续使用。但这也是为什么你不能/不应该传入包含在一个包里的模块路径。因为sys.path 可能不包含该包的目录,因此所有的导入将相对于与你预期的包不同的目录。

4、对包使用 -m
执行 Python 包的正确方法是使用 -m 并指定要运行的包名。

python -m spam
它在底层使用了runpy [5]。要在你的项目中做到这点,只需要在包里指定一个__main__.py 文件,它将被当成__main__ 执行。而且子模块可以像任何其它模块一样导入,因此你可以对其进行各种测试。

我知道有些人喜欢在一个包里写一个main 子模块,然后将其__main__.py 写成:

from . import main

if name == "__main__":

main.main()
就我个人而言,我不感冒于单独的main 模块,而是直接将所有相关的代码放入__main__.py ,因为我感觉这些模块名是多余的。

(译注:即作者不关心作为入口文件的"main"或者“__main__”模块,因为执行时只需用它们的包名即可。我认为这也暗示了入口模块不该再被其它模块 import。我上篇文章 [6]比作者的观点激进,认为连那句 if 语句都不该写。)

5、目录
定义__main__.py也可以扩展到目录。如果你看一下促成此博客文章的示例,python news 可执行,就是因为 news 目录有一个 __main__.py 文件。该目录就像一个文件路径被 Python 执行了。

现在你可能会问:“为什么不直接指定文件路径呢?”好吧,坦白说,关于文件路径,有件事得说清楚。😄在发布过程中,我可以简单地写上说明,让运行python news/announce.py ,但是并没有确切的理由说明这种机制何时存在。

再加上我以后可以更改文件名,而且没人会注意到。再加上我知道代码会带有辅助文件,因此将其放在目录中而不是单独作为单个文件是有意义的。

当然,我也可以将它变为一个使用 -m 的包,但是没必要,因为 announce 脚本很简单,我知道它要保持成为一个单独的自足的文件(少于 200 行,并且测试模块也大约是相同的长度)。

况且,__main__.py 文件非常简单。

import runpy

Change 'announce' to whatever module you want to run.
runpy.run_module('announce', run_name='__main__', alter_sys=True)
现在显然必须要处理依赖关系,但是如果你的脚本仅使用标准库或将依赖模块放在__main__.py 旁边(译注:即同级目录),那么就足够了!

(译注:我觉得作者在此有点“炫技”了,因为这种写法的前提是得知道 runpy 的用法,但是就像前一条所写的用 -m 参数运行一个包,在底层也是用了 runpy。不过炫技的好处也非常明显,即__main__.py 里不用导入 announce 模块,还是以它为主模块执行,也就不会破坏原来的依赖导入关系)

6、执行一个压缩文件
如果你确实有多个文件和/或依赖模块,并且希望将所有代码作为一个单元发布,你可以用一个__main__.py ,放置在一个压缩文件中,并把压缩文件所在目录放在 sys.path 里,Python 会替你运行__main__.py 文件。

将一个压缩包传给 Python
python app.pyz
人们现在习惯上用 .pyz 文件扩展名来命名此类压缩文件,但这纯粹是传统,不会影响任何东西;你当然也可以用 .zip 文件扩展名。

为了简化创建此类可执行的压缩文件,标准库提供了zipapp [7]模块。它会为你生成__main__.py并添加一条组织行(shebang line),因此你甚至不需要指定 python,如果你不想在 UNIX 上指定它的话。如果你想移动一堆纯 Python 代码,这是一种不错的方法。

不幸的是,仅当压缩文件包含的所有代码都是纯 Python 时,才能这样运行压缩文件。执行压缩文件对扩展模块无效(这就是为什么 setuptools 有一个 zip_safe [8]标志的原因)。(译注:扩展模块 extension module,即 C/C++ 之类的非 Python 文件)

要加载扩展模块,Python 必须调用 dlopen() [9]函数,它要传入一个文件路径,但当该文件路径就包含在压缩文件内时,这显然不起作用。

我知道至少有一个人与 glibc 团队交谈过,关于支持将内存缓冲区传入压缩文件,以便 Python 可以将扩展模块读入内存,并将其传给压缩文件,但是如果内存为此服务,glibc 团队并不同意。

但是,并非所有希望都丧失了!你可以使用诸如shiv [10]之类的项目,它会捆绑(bundle)你的代码,然后提供一个__main__.py 来处理压缩文件的提取、缓存,然后为你执行代码。尽管不如纯 Python 解决方案理想,但它确实可行,并且在这种情况下算得上是优雅的。

相关文章
|
21天前
|
开发框架 数据建模 中间件
Python中的装饰器:简化代码,增强功能
在Python的世界里,装饰器是那些静悄悄的幕后英雄。它们不张扬,却能默默地为函数或类增添强大的功能。本文将带你了解装饰器的魅力所在,从基础概念到实际应用,我们一步步揭开装饰器的神秘面纱。准备好了吗?让我们开始这段简洁而富有启发性的旅程吧!
28 6
|
14天前
|
数据可视化 Python
以下是一些常用的图表类型及其Python代码示例,使用Matplotlib和Seaborn库。
通过这些思维导图和分析说明表,您可以更直观地理解和选择适合的数据可视化图表类型,帮助更有效地展示和分析数据。
57 8
|
21天前
|
API Python
【Azure Developer】分享一段Python代码调用Graph API创建用户的示例
分享一段Python代码调用Graph API创建用户的示例
44 11
|
23天前
|
测试技术 Python
探索Python中的装饰器:简化代码,增强功能
在Python的世界中,装饰器是那些能够为我们的代码增添魔力的小精灵。它们不仅让代码看起来更加优雅,还能在不改变原有函数定义的情况下,增加额外的功能。本文将通过生动的例子和易于理解的语言,带你领略装饰器的奥秘,从基础概念到实际应用,一起开启Python装饰器的奇妙旅程。
35 11
|
19天前
|
Python
探索Python中的装饰器:简化代码,增强功能
在Python的世界里,装饰器就像是给函数穿上了一件神奇的外套,让它们拥有了超能力。本文将通过浅显易懂的语言和生动的比喻,带你了解装饰器的基本概念、使用方法以及它们如何让你的代码变得更加简洁高效。让我们一起揭开装饰器的神秘面纱,看看它是如何在不改变函数核心逻辑的情况下,为函数增添新功能的吧!
|
19天前
|
程序员 测试技术 数据安全/隐私保护
深入理解Python装饰器:提升代码重用与可读性
本文旨在为中高级Python开发者提供一份关于装饰器的深度解析。通过探讨装饰器的基本原理、类型以及在实际项目中的应用案例,帮助读者更好地理解并运用这一强大的语言特性。不同于常规摘要,本文将以一个实际的软件开发场景引入,逐步揭示装饰器如何优化代码结构,提高开发效率和代码质量。
44 6
|
24天前
|
Python
如何提高Python代码的可读性?
如何提高Python代码的可读性?
38 4
|
24天前
|
Python
Python编程入门:从零开始的代码旅程
本文是一篇针对Python编程初学者的入门指南,将介绍Python的基本语法、数据类型、控制结构以及函数等概念。文章旨在帮助读者快速掌握Python编程的基础知识,并能够编写简单的Python程序。通过本文的学习,读者将能够理解Python代码的基本结构和逻辑,为进一步深入学习打下坚实的基础。
|
28天前
|
设计模式 监控 程序员
Python中的装饰器:功能增强与代码复用的利器####
本文深入探讨了Python中装饰器的工作原理、应用场景及其在提升代码可读性、减少重复劳动方面的优势。不同于传统方法的冗长和复杂,装饰器提供了一种优雅且高效的方式来增强函数或方法的功能。通过具体实例,我们将揭示装饰器如何简化错误处理、日志记录及性能监控等常见任务,使开发者能够专注于核心业务逻辑的实现。 ####
|
26天前
|
存储 设计模式 缓存
Python中的装饰器:代码的魔法增强剂####
本文将深入探讨Python语言中一个强大而灵活的特性——装饰器。不同于传统的函数调用,装饰器提供了一种优雅的方式来扩展或修改函数行为,无需直接修改原函数代码。我们将通过实例分析,揭示装饰器的定义、工作原理及其在实际项目中的应用价值,旨在帮助开发者更好地理解和利用这一高级功能,提升代码的可读性与维护性。 ####