pig:是否可以对PythonUDF使用pytz或dateutils?

niwlg2el  于 2021-06-21  发布在  Pig
关注(0)|答案(2)|浏览(327)

我正在使用 datetime 在我的应用程序中使用的一些python udf中 pig 脚本。到现在为止,一直都还不错。我在cloudera 5.5上使用pig 12.0
但是,我也需要使用 pytz 或者 dateutil 包,它们似乎不是普通python安装的一部分。
我能在我的房间里用吗 Pig 某些方面的自定义项?如果是,怎么做?我想 dateutil 是安装在我的节点上的(我不是管理员,所以如何才能实际检查这种情况?)

import sys

# I append the path to dateutil on my local windows machine. Is that correct?

sys.path.append('C:/Users/me/AppData/Local/Continuum/Anaconda2/lib/site-packages')

from dateutil import tz

在我的 udfs.py 脚本,我得到:

2016-08-30 09:56:06,572 [main] ERROR org.apache.pig.tools.grunt.Grunt - ERROR 1121: Python Error. Traceback (most recent call last):
  File "udfs.py", line 23, in <module>
    from dateutil import tz
ImportError: No module named dateutil

当我运行我的Pig脚本。
所有其他python udf(使用 datetime 例如)工作得很好。你知道怎么解决吗?
非常感谢!
更新
在玩了一点python路径之后,我现在可以

import dateutil

(至少清管器不会坠毁)。但如果我尝试:

from dateutil import tz

我出错了。

from dateutil import tz 
  File "/opt/python/lib/python2.7/site-packages/dateutil/tz.py", line 16, in <module>
    from six import string_types, PY3
  File "/opt/python/lib/python2.7/site-packages/six.py", line 604, in <module>
    viewkeys = operator.methodcaller("viewkeys")
AttributeError: type object 'org.python.modules.operator' has no attribute 'methodcaller'

如何克服?我使用tz的方式如下

to_zone = dateutil.tz.gettz('US/Eastern')
from_zone = dateutil.tz.gettz('UTC')

然后我改变时间戳的时区。我可以导入dateutil来完成吗?正确的语法是什么?
更新2
按照黑帮的建议,我可以

import sys
sys.path.append('/opt/python/lib/python2.7/site-packages')
sys.path.append('/opt/python/lib/python2.7/site-packages/pytz/zoneinfo')

import pytz

但现在我又犯错误了

Caused by: Traceback (most recent call last): File "udfs.py", line 158, in to_date_local File "__pyclasspath__/pytz/__init__.py", line 180, in timezone pytz.exceptions.UnknownTimeZoneError: 'America/New_York'

当我定义

to_zone = pytz.timezone('America/New_York')
from_zone = pytz.timezone('UTC')

在这里发现了一些提示unknowntimezoneerror使用py2exe编译的python应用程序引发的异常
怎么办?啊,我只想在Pig身上转换时区:(

wgx48brx

wgx48brx1#

您可能知道,所有python udf函数都不是由python解释器执行的,而是由pig分发的jython。默认情况下,在0.12.0中应该是Jython2.5.3。不幸的是 six 包支持从python2.6开始的python,它是 dateutil . 然而 pytz 似乎没有这种依赖关系,应该支持从python2.4开始的python版本。
所以为了实现你的目标,你应该 pytz 包到2.5版的所有节点,并在pig udf中添加它的路径 sys.path . 如果你完成同样的步骤 dateutil 一切都应该如你所愿。我们使用的方法和 pygeoip 它就像一个魔咒。

它是怎么工作的

当您运行引用一些python udf(更准确地说是jython udf)的pig脚本时,您的脚本将被编译为map/reduce作业,所有这些都是 REGISTER ed文件包含在jar文件中,并分布在实际执行代码的节点上。现在,当执行代码时,jython解释器将从java代码启动并执行。所以现在,当python代码在参与计算的每个节点上执行时,所有python导入都在节点上本地解析。从标准库导入是从jython实现中获取的,但是所有的“包”都必须安装在其他地方,因为没有 pip 为了它。因此,要使外部软件包可用于python udf,您必须使用其他工具手动安装所需的软件包 pip 或者从源代码处安装,但请记住下载与Python2.5兼容的软件包!然后在每个udf文件中,您都必须附加 site-packages 在每个节点上安装软件包(在每个节点上使用相同的目录很重要)。例如:

import sys
sys.path.append('/path/to/site-packages')

# Imports of non-stdlib packages

概念证明

假设我们有以下文件: /opt/pytz_test/test_pytz.pig :

REGISTER '/opt/pytz_test/test_pytz_udf.py' using jython as test;

A = LOAD '/opt/pytz_test/test_pytz_data.csv' AS (timestamp:int);
B = FOREACH A GENERATE
    test.to_date_local(timestamp);

STORE B INTO '/tmp/test_pytz_output.csv' using PigStorage(',');
``` `/opt/pytz_test/test_pytz_udf.py` :

from datetime import datetime
import sys

sys.path.append('/usr/lib/python2.6/site-packages/')

import pytz

@outputSchema('date:chararray')
def to_date_local(unix_timestamp):
"""
converts unix timestamp to a rounded date
"""
to_zone = pytz.timezone('America/New_York')
from_zone = pytz.timezone('UTC')

try :
    as_datetime = datetime.utcfromtimestamp(unix_timestamp)
        .replace(tzinfo=from_zone).astimezone(to_zone)
        .date().strftime('%Y-%m-%d')
except:
    as_datetime = unix_timestamp
return as_datetime

``` /opt/pytz_test/test_pytz_data.csv :

1294778181
1294778182
1294778183
1294778184

现在让我们安装 pytz 在我们的节点上(必须使用 pytz 与Python2.5(2.5-2.7)兼容,在我的例子中,我将使用Python2.6): sudo pip2.6 install pytz 请确认,那个文件 /opt/pytz_test/test_pytz_udf.py 添加到 sys.path 参考 site-packages 哪里 pytz 已安装。
现在,一旦我们用测试脚本运行pig: pig -x local /opt/pytz_test/test_pytz.pig 我们应该能够读取工作的输出,其中应列出:

2011-01-11
2011-01-11
2011-01-11
2011-01-11
ecfsfe2w

ecfsfe2w2#

从一个不同但相关的问题的答案来看,只要资源在每个节点上都可用,您就应该能够使用它们。
我认为您可以添加这个关于jython的答案中描述的路径,并像往常一样加载模块。
在python脚本中将位置附加到sys.path:

import sys
sys.path.append('/usr/local/lib/python2.7/dist-packages')
import happybase

相关问题