我不确定之前是否曾经问过这个问题,但我想知道如何在python中实现类似于set set的语法来模仿UNIX SHELL管道。 特别是,如何使用可以生成,修改或使用记录流的“普通python函数”,并且可以使用“。”将它们粘合在一起。操作
一个简单的例子,假设python函数像Unix程序:
在unix中我们可以做到:
ls | egrep '^a' | wc -l
计算当前目录中以“a”开头的文件。 怎么样:
from unixtools import *
ls().egrep('^a').wc(countLines=True)
并且ls的实现可以像生成器一样:
@pipeline
def ls():
for file in glob.glob("*"):
yield file
我省略了明显的胶水代码,这样就可以将 ls 与管道的其他“命令”连接起来。
@pipeline 是尝试使用装饰器将普通python函数转换为管道协议的成员。
我意识到这可以使用python的传统语法来完成,它的可读性较低,迫使你反向编写,而且更容易出错:
wc(countLines=True,input=egrep("^a",input=ls()))
我想我们可以研究python pyquery 的实现来搞清楚。
答案 0 :(得分:0)
显然,python管道包非常接近我的要求,我不知道它。
所以,我正在回答我自己的问题,因为管道包文档对我说明的问题不是很直观。特别是在实现完整的unix shell管道语义时。最后,关于一些常见的unix技巧还存在一些尚未解决的问题。
我们可以使用@Pipe装饰器创建一个生成器作为python生成器。 请注意,这种类型的生产者只能是管道的第一个成员:
SharedModule
与在Unix中一样,您可以定义一个变换器,它可以转换输入并生成输出:
@NgModule({
imports: [
// ...
SharedModule
],
declarations: [
// ...
],
exports: [
// ...
]
})
export class AppModule {
// ...
}
我们可以使用“管道”语法来连接生产者和变换器,这类似于Unix Shell管道的语法:
from pipe import Pipe
@Pipe
def producer(arg=10):
for x in range(arg):
yield x
与Unix shell不同,这不会产生任何输出;-( 您可以编写消费者,消费者输入并打印一些内容:
@Pipe
def transformer(iterable, arg=2):
for x in iterable:
if x % arg == 0: yield x*2
现在连接将按预期工作:
producer() | transformer()
有趣的是,在第二个或更多个管道元素上,我们可以省略括号,只使用管道函数的名称:
@Pipe
def consumer(iterable):
for x in iterable:
print(x)
我喜欢的另一个功能,相当于SHELL“here document”:
producer() | transformer() | consumer()
在这种情况下,[1,2,3,4]被解释为生成器可以生成的值序列,并且“管道”到管道中的下一个元素。
我们当然可以收集管道结果:
producer(10) | transformer | consumer
现在终于有些情况下如何处理“管道”并不是很明显:
目前尚不清楚如何在SHELL中进行等效的stdout合并:
[1,2,3,4] | transformer | consumer
也许使用“cat”生成器,能够连接所有可迭代的输入?
a = [1,2,3,4] | transformer | consumer
还不清楚如何只使用管道的一些元素,然后继续使用另一个函数,就像在UNIX SHELL中一样:
(echo today ; date) | wc
在这种情况下,read消耗第一行,cat看到其余的行。我们可以重载“(”和“)”符号吗?