将模块作为可调用管道加载的包。
modpipe的Python项目详细描述
…图片::https://img.shields.io/pypi/v/modpipe.svg
:目标:https://pypi.python.org/pypi/modpipe
…图片::https://img.shields.io/travis/jbn/modpipe.svg
:目标:https://travis ci.org/jbn/modpipe
…图片::https://coveralls.io/repos/github/jbn/modpipe/badge.svg?branch=master
:目标:https://coveralls.io/github/jbn/modpipe?branch=master
=
=
==modpipe:modules-as-pipelines
=
=
=
-
-
-
这是什么?
----
将模块加载为可调用管道的自定包。
----
安装代码块::bash
pip install modpipe
但是,当前的主分支不支持酸洗。
直到我的'pr<;https://github.com/aliles/funcsigs/pull/33>;``被接受,pypi包才会在spark环境中工作。上面的pip
命令将安装我的分支。
----
这是为什么?
----
认识到这个模式,这个包使得使用
模块作为管道(特别是在etl上下文中)变得更容易。
————
我能看一个例子吗?
----
您可以将转换函数
累加在"inserte_pipeline.py"中。当下列代码运行时,
…代码块:python
import modpipe
离子。满嘴都是。
具体地说,假设您在``instept_pipeline.py``,
代码块::python
def两次(x):
return x*2
def怪异对(x):
return x,-x
代码块::python
def f(x):
返回奇怪的配对(两次(x))
——
那又怎样?
——
如果您做了大量痛苦的etl工作,这可能会让您觉得很有用。
如果你不这样做,你可能会说,"那又怎样?"不幸的是,我认为如果没有一个动态屏幕的开发人员(xxx:todo),这个
就不能很好地交流了。
但是,现在,我将依靠tim peter's wonderful
`pep20<;https://www.python.org/dev/peps/pep-0020/pep20&g t;中的最后一句话:`,
好主意——让我们做更多的事情!
通过将转换代码移动到模块中,您可以腾出笔记本
(和认知空间)用于后续步骤。如果您花一点时间
正确命名模块,则导航起来会比较容易。如果
将转换代码划分为不同的逻辑单元,它就有点
健壮。而且,如果您用断言填充管道模块代码,它会记录您对数据的期望。
每个人都希望用与编写其他代码相同的方式编写etl代码:
使用良好的测试套件仔细编写。但是,实际上,由于各种限制,我们不会这样做。另外,这是非常乏味的代码。
这个包(以及我从中提取的那个包,
`vaquero<;https://github.com/jbn/vaquero>;```u)可以识别竞争的需求和任务的实际情况,并与您合作。
----
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
默认情况下,管道中不输入带下划线前缀的可调用项。
假设这些可调用函数是由
在线性化管道中真正需要的函数使用的**辅助函数。
代码块::python
def_encode_as_binary(x):默认不在管道中!
return bin(x)[2:].rjust(32,'0')
return[廑encode廑u as廑binary(seed)for seed in seeds]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
如上所述,单元测试etl代码是一件痛苦的事情。而且,由于脏数据
几乎连续违反预期,严重阻碍了进展。
与其依赖于转换函数的单元测试,
更容易编写(在模块上下文中)断言
,这些断言记录您的假设,并通过在重新/导入时大声失败来防止意外的回归
。
以下(人工)示例确保管道的sqrt函数
正确计算平方根并返回与给定数值类型相同的结果。
代码块::python
def sqrt(x):
返回类型(x)(x**0.5)
assert sqrt(1776)==42,"噢!"#如果代码错误,则会大声失败!
~~~~~~~~~~~~~~~~~~~~~~~~~
但是,在许多上下文中,它们使您很难对代码失败时的行为进行推理。在大多数情况下,
管道是模块中函数的线性组合。
因此,如果第85行的函数在使用时引发异常,您将知道只有上面的函数已经执行。这是一个非常有用的认知设备,特别是当你从你的代码中走了六个月,并且只有当它变成一个问题时才再次访问它。有时,
有必要:1)提前中止管道或2)跳过某些函数。这个包为这两种情况都提供了一个sentinel返回值。代码块::python
from lxml.html import fromstring
from modpipe import skipto,done
如果raw_html.strip():
返回{'doc':fromstring(raw_html)}
否则:
返回done(none)任何内容都不能完成!中止!
def extract_title(d):
对于d['doc']中的title。xpath("//title/text()"):
d['title']=title
如果d['title']中有'error'。lower():
返回skipo(cleanup,d)跳到cleanup!
否则:
返回d
t_headers``和'cleanup``在传递的dict上进行了
转换。为了在通信
变异时减少loc,两者都没有返回值。这种风格有利有弊。
但是,无论如何,``modpipe``通过假设返回``none``的
函数的给定参数应该传递给
管道中的下一个函数来处理它。因此,cleanup接收到"d"。
这就引出了一个问题:如果您不想返回任何内容,如何返回?在
这种情况下,需要返回"result"。例如,
…代码块::来自modpipe import r的pythonesult
def f(s):
tok=s.upper().strip()
如果tok else result(none)或done(none)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
元组是特殊的
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
管道中下一个函数的rity,modpipe star在调用下一个函数时展开
,否则,它将执行f(res)。
…代码块::python
def(x):
return x,-x即add(x,-x)
def g(x,y):
return x+y,x*y,即h(x+y,x*y)
def h(items):
return sum(items)
这仅适用于元组和元组。(也就是说,如果返回一个列表,它总是将整个列表作为参数传递。)您会注意到调用结构不允许使用关键字参数。我试过解决这个问题,但没有发现任何不具侵入性的东西。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
还有别的吗?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
是。"modpipe"中的管道非常友好。尽管spark团队不建议再使用rdd,但是
spark对于编写etl管道很有用。但是,python对象序列化和反序列化给pyspark本身(即rdd上的"map")的转换链增加了很多开销。如果您将
转换收集到序列化为模块的逻辑单元,它将分摊
酸洗相关的费用。这不是scala的速度,但至少你可以以更高效的方式利用现有的基础设施。
~~~~~
misc
~~~~
我想我是从"pymc3<;https://docs.pymc.io/>;"中得到这个想法的。对于主要的
版本bump,很多例子开始使用模块,我一开始觉得它很烦人。然后我意识到这是多么美好。由于建模和
etl往往是并驾齐驱的(尽管比例是1:99),我开始用同样的方式编写
etl代码。我肯定我不是第一个这么做的人,但我以前没见过。(这可能只是很多人不写就自然而然地做的事情之一。)
我还想指出"倭黑猩猩"https://github.com/python bonobo/bonobo>;`。
它更加成熟和灵活。根据文档,
Bonobo是对一个旧Python2.7工具的年轻重写,该工具在生产过程中每天运行数百万次
转换。虽然它可能还没有完成或完全稳定(请允许我们达到1.0),
基本的东西都在那里。
但是,对于90%的项目来说,vaquero(使用modpipe)更适合我。
=
=
history
=
0.0.1(2018-04-30)
-----
*PYPI上的第一个版本。
:目标:https://pypi.python.org/pypi/modpipe
…图片::https://img.shields.io/travis/jbn/modpipe.svg
:目标:https://travis ci.org/jbn/modpipe
…图片::https://coveralls.io/repos/github/jbn/modpipe/badge.svg?branch=master
:目标:https://coveralls.io/github/jbn/modpipe?branch=master
=
=
==modpipe:modules-as-pipelines
=
=
=
-
-
-
这是什么?
----
将模块加载为可调用管道的自定包。
----
安装代码块::bash
pip install modpipe
但是,当前的主分支不支持酸洗。
直到我的'pr<;https://github.com/aliles/funcsigs/pull/33>;``被接受,pypi包才会在spark环境中工作。上面的pip
命令将安装我的分支。
----
这是为什么?
----
认识到这个模式,这个包使得使用
模块作为管道(特别是在etl上下文中)变得更容易。
————
我能看一个例子吗?
----
您可以将转换函数
累加在"inserte_pipeline.py"中。当下列代码运行时,
…代码块:python
import modpipe
离子。满嘴都是。
具体地说,假设您在``instept_pipeline.py``,
代码块::python
def两次(x):
return x*2
def怪异对(x):
return x,-x
代码块::python
def f(x):
返回奇怪的配对(两次(x))
——
那又怎样?
——
如果您做了大量痛苦的etl工作,这可能会让您觉得很有用。
如果你不这样做,你可能会说,"那又怎样?"不幸的是,我认为如果没有一个动态屏幕的开发人员(xxx:todo),这个
就不能很好地交流了。
但是,现在,我将依靠tim peter's wonderful
`pep20<;https://www.python.org/dev/peps/pep-0020/pep20&g t;中的最后一句话:`,
好主意——让我们做更多的事情!
通过将转换代码移动到模块中,您可以腾出笔记本
(和认知空间)用于后续步骤。如果您花一点时间
正确命名模块,则导航起来会比较容易。如果
将转换代码划分为不同的逻辑单元,它就有点
健壮。而且,如果您用断言填充管道模块代码,它会记录您对数据的期望。
每个人都希望用与编写其他代码相同的方式编写etl代码:
使用良好的测试套件仔细编写。但是,实际上,由于各种限制,我们不会这样做。另外,这是非常乏味的代码。
这个包(以及我从中提取的那个包,
`vaquero<;https://github.com/jbn/vaquero>;```u)可以识别竞争的需求和任务的实际情况,并与您合作。
----
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
默认情况下,管道中不输入带下划线前缀的可调用项。
假设这些可调用函数是由
在线性化管道中真正需要的函数使用的**辅助函数。
代码块::python
def_encode_as_binary(x):默认不在管道中!
return bin(x)[2:].rjust(32,'0')
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
如上所述,单元测试etl代码是一件痛苦的事情。而且,由于脏数据
几乎连续违反预期,严重阻碍了进展。
与其依赖于转换函数的单元测试,
更容易编写(在模块上下文中)断言
,这些断言记录您的假设,并通过在重新/导入时大声失败来防止意外的回归
。
以下(人工)示例确保管道的sqrt函数
正确计算平方根并返回与给定数值类型相同的结果。
代码块::python
def sqrt(x):
返回类型(x)(x**0.5)
assert sqrt(1776)==42,"噢!"#如果代码错误,则会大声失败!
~~~~~~~~~~~~~~~~~~~~~~~~~
但是,在许多上下文中,它们使您很难对代码失败时的行为进行推理。在大多数情况下,
管道是模块中函数的线性组合。
因此,如果第85行的函数在使用时引发异常,您将知道只有上面的函数已经执行。这是一个非常有用的认知设备,特别是当你从你的代码中走了六个月,并且只有当它变成一个问题时才再次访问它。有时,
有必要:1)提前中止管道或2)跳过某些函数。这个包为这两种情况都提供了一个sentinel返回值。代码块::python
from lxml.html import fromstring
from modpipe import skipto,done
返回{'doc':fromstring(raw_html)}
否则:
返回done(none)任何内容都不能完成!中止!
def extract_title(d):
对于d['doc']中的title。xpath("//title/text()"):
d['title']=title
如果d['title']中有'error'。lower():
返回skipo(cleanup,d)跳到cleanup!
否则:
返回d
t_headers``和'cleanup``在传递的dict上进行了
转换。为了在通信
变异时减少loc,两者都没有返回值。这种风格有利有弊。
但是,无论如何,``modpipe``通过假设返回``none``的
函数的给定参数应该传递给
管道中的下一个函数来处理它。因此,cleanup接收到"d"。
这就引出了一个问题:如果您不想返回任何内容,如何返回?在
这种情况下,需要返回"result"。例如,
…代码块::来自modpipe import r的pythonesult
def f(s):
tok=s.upper().strip()
如果tok else result(none)或done(none)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
元组是特殊的
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
管道中下一个函数的rity,modpipe star在调用下一个函数时展开
,否则,它将执行f(res)。
…代码块::python
def(x):
return x,-x即add(x,-x)
def g(x,y):
return x+y,x*y,即h(x+y,x*y)
def h(items):
return sum(items)
这仅适用于元组和元组。(也就是说,如果返回一个列表,它总是将整个列表作为参数传递。)您会注意到调用结构不允许使用关键字参数。我试过解决这个问题,但没有发现任何不具侵入性的东西。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
还有别的吗?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
是。"modpipe"中的管道非常友好。尽管spark团队不建议再使用rdd,但是
spark对于编写etl管道很有用。但是,python对象序列化和反序列化给pyspark本身(即rdd上的"map")的转换链增加了很多开销。如果您将
转换收集到序列化为模块的逻辑单元,它将分摊
酸洗相关的费用。这不是scala的速度,但至少你可以以更高效的方式利用现有的基础设施。
~~~~~
misc
~~~~
我想我是从"pymc3<;https://docs.pymc.io/>;"中得到这个想法的。对于主要的
版本bump,很多例子开始使用模块,我一开始觉得它很烦人。然后我意识到这是多么美好。由于建模和
etl往往是并驾齐驱的(尽管比例是1:99),我开始用同样的方式编写
etl代码。我肯定我不是第一个这么做的人,但我以前没见过。(这可能只是很多人不写就自然而然地做的事情之一。)
我还想指出"倭黑猩猩"https://github.com/python bonobo/bonobo>;`。
它更加成熟和灵活。根据文档,
Bonobo是对一个旧Python2.7工具的年轻重写,该工具在生产过程中每天运行数百万次
转换。虽然它可能还没有完成或完全稳定(请允许我们达到1.0),
基本的东西都在那里。
但是,对于90%的项目来说,vaquero(使用modpipe)更适合我。
=
=
history
=
0.0.1(2018-04-30)
-----
*PYPI上的第一个版本。