IPython inline!bang shell命令

bfrts1fy  于 2023-03-30  发布在  Shell
关注(0)|答案(1)|浏览(124)

有没有一种方法可以内联使用IPython !(bang)?或者有没有一种很好的通用Python方法可以运行shell命令并将其输出捕获到列表或字符串中?你可以使用Python的os.listdir方法和其他shell Package 器方法,但是你必须知道 Package 常见shell命令的Python方法。
例如,使用cat内联,!cat /etc/os-release(我通常会在JupyterLab中运行)会引发语法错误:

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

这与walrus操作符沿着,允许在解析中进行有趣的文件系统输出处理。
否则,您必须通过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}
sczxawaw

sczxawaw1#

subprocess使调用shell变得很简单。您需要做一些额外的事情,使其看起来像!的直接替代品。但是编写一个 Package 器函数来帮助实现这一点很简单。

import subprocess

class StringResult:
    def __init__(self, result):
        self.result = result

    def __iter__(self):
        return iter(str(self).splitlines())

    def __str__(self):
        return self.result.stdout.decode()

    def __bool__(self):
        return self.result.returncode == 0

def run(*args, **kwargs):
    result = subprocess.run(*args, shell=True, capture_output=True, **kwargs)
    return StringResult(result)

glob = '*.py'
# a very silly way to print "py" if any .py files exist
for line in run(f'ls -1 {glob} | cut -d . -f 2 | sort | uniq'):
    print(line)

if run('which python3'):
    print('Python 3 exists on this machine')

对于一些手工的黑客来说,这一切都很好,但是如果您正在编写程序或脚本,那么最好使用Python的原生特性。

相关问题