【发布时间】:2021-04-07 20:46:00
【问题描述】:
我个人觉得在 Python 中使用 os 和 system 既冗长又麻烦。因此,我喜欢在 IPython 中使用 bang 运算符 (!) 在文件系统上编写脚本,并以 $variable 或 {variable} 的形式进行变量扩展,如文档中的 here 所述。多年来,我广泛使用了它,最常见的是通过 shell 与 MRI 处理工具交互并管理它们的 MRI 输入和输出。
有没有办法在线使用 IPython ! (bang)?或者是否有一种很好的通用 Pythonic 方式来运行 shell 命令并在列表或字符串中捕获其输出?您可以使用 Python 的 os.listdir 方法和其他 shell 包装器方法,但是您必须知道包装常用 shell 命令的 Python 方法。当然,使用这些的好处是,您的代码也可以在 Windows 和 Linux 上运行。但是,如果您在 Windows 上使用 Python 进行编码,请删除您的 stackoverflow 帐户,但我离题了。 ;)
例如使用cat in-line,!cat /etc/os-release(我通常会在 Jupyter Lab 中运行它)会引发语法错误:
In [1]: os_release_info = {(split := info.split('='))[0]:split[1] for info in !cat /etc/os-release}
File "<ipython-input-4-b5d2c7182f4f>", line 1
os_release_info = {(split := info.split('='))[0]:split[1] for info in !cat /etc/os-release}
^
SyntaxError: invalid syntax
这与海象运算符一起允许人们在理解中进行有趣的文件系统输出处理。
否则,您必须通过 bang 操作符在单独的行上分离出 shell 命令:
Python 3.9.1 (default, Feb 3 2021, 07:04:15)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.20.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: os_release_cat = !cat /etc/os-release
In [2]: os_release_info = {(split := info.split('='))[0]:split[1] for info in os_release_cat}
【问题讨论】:
-
改用
pathlib.Path("/etc/os-release").read_text().splitlines()。 -
希望您已经意识到运行和解析像
ls这样的shell 命令是缓慢、脆弱且充满陷阱的,而os.listdir是快速、安全且健壮的。您是否考虑过寻找一个用 Python 实现常用 shell 命令的库? -
ipython shell 可以在行首捕获
!,在var=!cmd语法中,ipython.readthedocs.io/en/stable/interactive/…,但在其他任何地方,Python 解释器都会看到!并抱怨。 -
为什么运行和解析像
ls这样的shell命令“缓慢、脆弱、充满陷阱”?至少部分是因为您使用的是 shell 而不是直接与操作系统交互?
标签: python shell jupyter-notebook ipython jupyter-lab