跳转到主要内容

在shell中轻松运行Python!神奇,但从不神秘。

项目描述

pyp

Build Status Coverage Status Checked with mypy

在shell中轻松运行Python!神奇,但从不神秘。

安装

运行 pip install pypyp (注意额外的"yp"!)

pyp需要Python 3.8或更高版本。

工作原理

pyp将静态分析输入代码以检测未定义的变量。根据它发现的内容,它将按需转换输入代码的AST。然后我们编译并执行结果,或者如果使用--explain,将AST反解析为源代码。

示例

本节将向您介绍使用pyp的细节,并希望满足您对许多常用shell工具的需求。要查看速查表/tldr,请运行pyp --help

pyp可以轻松地应用于输入的每一行。

只需使用一个魔法变量xlline来引用当前行。

# pyp like cut
ls | pyp 'x[:3]'
ps x | pyp 'line.split()[4]'

pyp也可以轻松地将Python代码应用于整个输入。

使用魔法变量lines表示去除尾部的行的列表,或使用stdin表示sys.stdin

# pyp like wc -c
cat /usr/share/dict/words | pyp 'len(stdin.read())'

# pyp like awk
seq 1 5 | pyp 'sum(map(int, lines))'

pyp会自动导入您使用的模块。

# pyp like sh
echo echo echo | pyp 'subprocess.run(lines[0], shell=True); pass'

# pyp like jq
curl -s 'https://api.github.com/repos/hauntsaninja/pyp/commits?per_page=1' | pyp 'json.load(stdin)[0]["commit"]["author"]'

# pyp like egrep
cat /usr/share/dict/words | pyp 'x if re.search("(p|m)yth", x) else None'

对于collectionsmathitertoolspathlib.Pathpprint.pp,pyp会自己解决,即使您没有使用限定名。

# pyp like bc
pyp 'sqrt(5)'

# pyp like ${x##*.}
ls | pyp 'Path(x).suffix'

pyp可以使用魔法变量iidxindex提供对循环索引的访问。

# pyp like line numbers
cat setup.py | pyp 'f"{idx+1: >3} {x}"'

请注意,到目前为止,您不需要调用print

默认情况下,pyp 会打印代码中的最后一个表达式——除非它评估为 None(或最后一个语句是 pass)。您始终可以显式调用 print,在这种情况下,pyp 将不会打扰您。

# pyp like grep
cat /usr/share/dict/words | pyp 'x if "python" in x else None'
cat /usr/share/dict/words | pyp 'if "python" in x: print(x); "this will not be printed"'

pyp 会尝试智能地打印字典和可迭代对象。

这使得 pyp 的输出更容易与 shell 工具组合。再次强调,显式打印将停止这种魔法,但如果您希望重新启用,pyp 提供了 pypprint 函数。

# pyp like tail
ls | pyp 'lines[-10:]'

# pyp like sort
ls | pyp 'sorted(lines)'
ls | pyp 'print(f"Sorting {len(lines)} lines"); pypprint(sorted(lines))'

# pyp like sort | uniq
ls | pyp 'sorted(set(lines))'

pyp 允许您在处理输入前后运行 Python 片段。

注意,如果您遇到分号问题并希望换行(而不用在 shell 中使用多行字符串),只需向 pyp 传递另一个字符串即可。您也可以始终将 pyp 管道到 pyp!

# pyp like anything!
ps aux | pyp -b 'd = defaultdict(list)' 'user, pid, *_ = x.split()' 'd[user].append(pid)' -a 'del d["root"]' -a 'd'

pyp 可以很神奇,但不必神秘!

使用 --explain--script,pyp 将输出一个与它将要运行的脚本等效的输出。这也可以作为更复杂脚本的 useful 起始点。

pyp --explain -b 'd = defaultdict(list)' 'user, pid, *_ = x.split()' 'd[user].append(pid)' -a 'del d["root"]' -a 'd'
#!/usr/bin/env python3
from collections import defaultdict
from pyp import pypprint
import sys
d = defaultdict(list)
for x in sys.stdin:
    x = x.rstrip('\n')
    (user, pid, *_) = x.split()
    d[user].append(pid)
del d['root']
if d is not None:
    pypprint(d)

如果您的命令遇到异常,pyp 将将跟踪信息重新构造到生成的代码中。

pyp 是可配置的。

将环境变量 PYP_CONFIG_PATH 指向一个包含以下内容的文件,例如

import numpy as np
import tensorflow as tf
from pipetools import *

def p95(data):
    return np.percentile(data, 95)

class PotentiallyUsefulClass: ...

当尝试定义未定义的名称时,pyp 会将此文件作为可能的定义来源进行静态分析。这意味着如果您没有使用 tf,我们不会导入 tensorflow!当然,--explain 将显示确切运行的内容(以及因此没有运行的内容!)

pyp --explain 'print(p95(list(map(float, stdin))))'
#!/usr/bin/env python3
import sys
import numpy as np

def p95(data):
    return np.percentile(data, 95)
stdin = sys.stdin
print(p95(list(map(float, stdin))))

注意,在配置中从类似 pipetools 的库中导入内容可以允许您达到高级别的语法糖

seq 1 110 | pyp 'lines > foreach(int) | where(X > 100) | group_by(X % 3) | sort_by(X[0])'

如果使用通配符导入,如果存在未定义的名称,我们需要导入这些模块,尽管在 happy path 中我们跳过了这一步。如果这对您很重要,那么请绝对不要在您的配置中使用 from tensorflow import *

pyp 允许您配置自己的魔法!

如果配置文件中的定义依赖于魔法变量,pyp 将按照有意义的方式进行替换。例如,将以下内容放入您的配置...

n = int(x)
f = x.split()
j = json.load(stdin)

import pandas as pd
csv = pd.read_csv(stdin)

...以使 pyp 对您的自定义用例更加便捷

ps | pyp 'f[3]'

cat commits.json | pyp 'j[0]["commit"]["author"]'

< cities.csv pyp 'csv.to_string()'

我有问题!

有关文档和示例,请参阅 FAQ。如果这不能回答您的问题,请提出一个 issue!

相关项目

Pyed Piper 即在提示符中的 Python 力量

pypyp 从这里获得了灵感(以及命令名称!)

Pyed Piper 已经死亡十年,并且仅适用于 Python 2,当 pypyp 被编写时;它最近似乎被复活了。Pyed Piper 比 pypyp 靠近常规 Python 语法和 API。特别是,Pyed Piper 强调在 Python 中进行管道,类似于您可以将 pipetools 与上面的配置示例中的 pypyp 结合起来的方式。

Pyped

Pyped 非常相似;相似到我不知道它时,我可能不会编写 pyp。但很高兴我没有,因为 Pyped 不执行我们做的 AST 内省和操作。这意味着

  • Pyped 依赖于您传入标志来告诉它做什么,而 pyp 可以从输入中明确推断意图。
  • 它不提供简单的自动打印,也不提供智能打印可迭代对象和字典。
  • 它硬编码了一个导入列表,并在您的系统上安装了一些库。此项目的自动导入适用于您使用的任何库。
  • 它没有像 --explain/--script 这样的功能。

然而,

  • 它有一些便利之处,例如输入的正则表达式分割,您需要自己在这里完成。
  • 它支持 Python 2 和 Python 3 的早期版本。
  • 它已经存在很长时间了。

piep / spy / pyfil / pythonpy / oneliner

自从编写了 pyp,发现比我想的还有更多替代方案 :-) 一些快速笔记

  • 其中大多数依赖于用户传递标志,例如 Pyped。
  • 其中大多数在自动打印方面存在限制,例如只能自动打印单个表达式,或者不很好地处理可迭代对象和字典。
  • 其中一些提供了进程内命令链的定制语法,这可能会很方便。
  • 其中一些专门支持JSON输入或运行shell命令等。
  • 其中一些通过自定义行/文件/流对象以有趣的方式暴露输入。
  • 其中一些在错误处理方面具有更高级的选项(尽管它们没有一个像pyp那样出色的回溯)。
  • 它们都没有像pyp那样强大的配置功能。
  • 它们都没有像--explain这样的功能。

无论如何,我已经按照个人偏好的顺序列出了上述项目。

mario

mario 是一种对使用Python进行shell处理的改进方案。它不使用未定义名称检测,而是依赖于可插拔的子命令系统。虽然子命令可能比 pyp 更冗长,但 mario 通过自动应用函数和自定义命令链语法来弥补一些不足。结果可能感觉有点 DSL 风格,而 pyp 则试图感觉非常接近编写 Python。

考虑使用 mario 如果

  • 您发现自己正在连接长序列的 pyp 命令,并希望能够在一个进程内进行命令链。
  • 您经常需要重复使用复杂的 pyp 命令,或者进行大量的特定领域shell处理,您希望能够用单个命令重复使用。
  • 您希望能够轻松地使用异步函数。

考虑 pyp 如果

  • 您希望最小化快速且简单的事情的按键次数。
  • 您想要一个最小化和轻量级的工具,感觉非常接近 Python。您不想记住命令。
  • 您愿意使用 Python 库来完成特定领域的繁重工作,以便轻松进行命令链或语法糖。您不介意(或想要能够)通过 --script 回退到脚本以处理复杂性。

xonsh

xonsh 是一种其语言是Python超集的shell;这更加雄心勃勃,与 pyp 很不同。pyp 对于单行管道用例更容易使用,但如果您需要在shell中使用更多Python,请查看 xonsh

awk

如果 awk 对您适用,您是如何来到这里的?

项目详情


下载文件

下载适用于您的平台的文件。如果您不确定选择哪一个,请了解更多关于 安装包 的信息。

源分发

pypyp-1.2.0.tar.gz (18.8 kB 查看哈希值)

上传时间

构建分发

pypyp-1.2.0-py3-none-any.whl (15.5 kB 查看哈希值)

上传时间: Python 3