我在datetime
脚本中使用的一些Python udfs中使用pig
。到现在为止还挺好。我在Cloudera 5.5上使用猪12.0
但是,我还需要使用pytz
或dateutil
包,它们似乎不是vanilla python安装的一部分。
我可以在某些方面在Pig
udfs中使用它们吗?如果是这样,怎么样?我认为我的节点上安装了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
当我运行我的猪脚本时。
我所有的其他python udfs(例如使用datetime
)都可以正常工作。知道怎么解决这个问题吗?
非常感谢!
更新
在使用python路径玩了一下之后,我现在能够
了import dateutil
(至少Pig不会崩溃)。但如果我尝试:
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
根据yakuza的建议,我能够
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 Exception Raised with Python Application Compiled with Py2Exe
找到了一些提示怎么办? Awww,我只想转换Pig中的时区:(
答案 0 :(得分:3)
好吧,你可能知道所有Python UDF函数都不是由Python解释器执行的,而是与Pig一起分发的Jython。默认情况下,在0.12.0中应为Jython 2.5.3。不幸的是,six
包从Python 2.6开始支持Python,dateutil
需要它的包。但是pytz
似乎没有这种依赖性,并且应该支持从Python 2.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
手动安装所需的程序包或从源代码安装,但请记住下载与Python 2.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
(它必须使用Python版本安装,其中pytz
与Python 2.5(2.5-2.7)兼容,在我的情况下我将使用Python 2.6 ):
sudo pip2.6 install pytz
请确保该文件 /opt/pytz_test/test_pytz_udf.py
添加sys.path
对已安装site-packages
的{{1}}的引用。
现在我们用我们的测试脚本运行Pig:
pytz
我们应该能够从我们的工作中读取输出,应该列出:
pig -x local /opt/pytz_test/test_pytz.pig
答案 1 :(得分:1)
从a different but related question的答案来看,只要资源在每个节点上都可用,您就应该能够使用资源。
我认为您可以按this answer regarding jython中所述添加路径,并照常加载模块。
将位置附加到Python脚本中的sys.path:
import sys sys.path.append('/usr/local/lib/python2.7/dist-packages') import happybase