作者 | BRETT CANNON
译者 | 豌豆花下猫@Python猫

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

前几天,一位合作者问这是如何工作的,似乎我们团队中的每个人都知道如何使用-m?请参阅我的有关带 -m 使用 pip 的文章[4],了解原因。

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

通过标准输入和管理

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

# 管道传内容给 python
echo "print('hi')" | python

如果将文件重定向到 Python,这显然也可以。

# 重定向一个文件给 python
python < spam.py

归功于 Python 的 UNIX 传统,这些都不太令人感到意外。

通过 -c 指定的字符串

如果你只需要快速地检查某些内容,则可以在命令行中将代码作为字符串传递。

# 使用 python 的 -c 参数
python -c "print('hi')"

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

文件的路径

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

# 指定 python 的文件路径
python spam.py

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

对包使用 -m

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

python -m spam

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

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

from . import mainif __name__ == "__main__":main.main()

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

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

目录

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

img

现在你可能会问:“为什么不直接指定文件路径呢?”好吧,坦白说,关于文件路径,有件事得说清楚。????在发布过程中,我可以简单地写上说明,让运行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 模块,还是以它为主模块执行,也就不会破坏原来的依赖导入关系)

执行一个压缩文件

如果你确实有多个文件和/或依赖模块,并且希望将所有代码作为一个单元发布,你可以用一个__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 解决方案理想,但它确实可行,并且在这种情况下算得上是优雅的。

原文链接:https://snarky.ca/the-many-ways-to-pass-code-to-python-from-the-terminal

推荐阅读
  • 性能超越最新序列推荐模型,华为诺亚方舟提出记忆增强的图神经网络

  • 阿里云科学家入选计算机顶会HPCA名人堂,他是什么来头?

  • 干货 | 基于SRS直播平台的监控系统之实现思路与过程

  • DevOps 在移动应用程序开发中扮演什么角色?

  • 又一国产数据库诞生!腾讯发布 TGDB,实时查询比 Neo4j 快 20-150 倍!

  • 稳定币经济:十大稳定币简史

你点的每个“在看”,我都认真当成了AI

涨见识了,在终端执行 Python 代码的 6 种方式相关推荐

  1. python交互式方式、代码文件方式_涨见识了,在终端执行 Python 代码的 6 种方式

    原作:BRETT CANNON 译者:豌豆花下猫@Python猫 英文:https://snarky.ca/the-many-ways-to-pass-code-to-python-from-the- ...

  2. python花猫_涨见识了,在终端执行 Python 代码的 6 种方式!

    原作: BRETT CANNON 译者:豌豆花下猫@Python猫 英文: https://snarky.ca/the-many-ways-to-pass-code-to-python-from-th ...

  3. 执行python代码的方式_涨见识了,在终端执行 Python 代码的 6 种方式!

    译者:豌豆花下猫@Python猫 为了我们推出的 VS Code 的 Python 插件 [1],我写了一个简单的脚本来生成变更日志 [2](类似于Towncrier [3],但简单些,支持 Mark ...

  4. 在终端执行 Python 代码的 6 种方法,原来还能这样!

    来自 | Python猫  编译 | 豌豆花下猫 原作 | BRETT CANNON 为了我们推出的 VS Code 的 Python 插件[1],我写了一个简单的脚本来生成变更日志[2](类似于To ...

  5. Pycharm中运行Python代码的几种方式

    Pycharm中运行Python代码的几种方式 在pycharm中的Python代码运行会出现各种奇葩的问题,比如,密码输入时不显示或没有提示,给我们带来一些麻烦,下面介绍几种代码运行的几种方式: 一 ...

  6. 执行 Python 程序的三种方式及Python 的 IDE —— `PyCharm`

    执行 Python 程序的三种方式 3.1. 解释器 python / python3 Python 的解释器 # 使用 python 2.x 解释器 $ python xxx.py# 使用 pyth ...

  7. python程序执行的两种方式_012.执行Python程序的两种方式

    一.执行Python程序的两种方式 1.1 交互式 在终端内输入python3,然后输入python代码 交互式环境下,敲完一条命令按下enter键马上能看到结果,调试程序方便.程序无法永久保存,关掉 ...

  8. 运行python程序的两种方式交互式和文件式_执行Python程序的两种方式

    交互式(了解) 交互式环境下,敲完一条命令按下enter键马上能看到结果,调试程序方便.程序无法永久保存,关掉cmd窗口数据就消失了. 命令行式(了解) 打开文本编辑器,在文本编辑器中写入一串字符. ...

  9. Python 执行Python程序的三种方式

    解释器 python / python3 python 的解释器 # 使用python 2.x 解释器 python xxx.py# 使用python 3.x 解释器 python3 xxx.py P ...

最新文章

  1. 【每日一算法】对称二叉树
  2. 我所了解的Chrome
  3. Module build failed (from ./node_modules/babel-loader/lib/index.js): Error: [BABEL] D:\moblie\web_co
  4. 免费开源剪辑软件Shotcut推荐和使用教程
  5. 一个前端的10年前端职业路
  6. NHibernate.3.0.Cookbook第三章第8节的翻译
  7. linux+npm+v+报错_linux下安装npm
  8. POJ1039+几何+直线于线段相交
  9. 机器学习十大经典算法-KMeans
  10. EF6 秘籍 2th:Entity Framework 入门(二)EF简介
  11. 基恩士光纤传感器怎么恢复出厂设置_光纤故障排查测试必备神器
  12. SLAM--DBow3
  13. android rom 刷机包下载地址,谷歌Android5.0 Nexus系列安卓ROM刷机包镜像/驱动下载地址发布...
  14. Kaggle入门 - TMDB 5000 电影推荐数据分析
  15. 2009-2019年五级(到村/居委会)行政区划代码数据
  16. 华为matebook13 win10系统重置登录密码
  17. 第一个虚拟仿真项目,冲冲冲
  18. python社区微信群_Python 打造微信群聊天机器人(带操作界面)-Go语言中文社区...
  19. 抖音浏览量的作用是什么?
  20. 【医学图像处理】X-ray 数字射线成像

热门文章

  1. JavaScript学习记录 (三) 函数和对象
  2. 数通手稿留档——BGP
  3. 纯JS导出excel(支持中文)
  4. PostgreSQL SQL 语言:并行查询
  5. 多个class相同的input标签 获取当前值!方法!
  6. wordpress jquery加载如何实现?
  7. VS新建类自动添加版本注释
  8. 我焦躁,并不只是心里承受,还是因为我上面担着。
  9. javascript实例
  10. 2019-03-20 Python爬取需要登录的有验证码的网站