目标:在constants.pig中为代码模块化定义了常量(%declare和%default)语句,并在其他猪文件中导入相同的语句。
根据文档:http://pig.apache.org/docs/r0.12.0/cont.html#import-macros,%declare和%default是宏中的有效语句。
问题Faced:Pig无法找到声明的参数。
Pig文件:constants.pig
%declare ACTIVE_VALUES 'UK';
猪文件:a.pig
IMPORT 'constants.pig';
A = LOAD 'a.csv' using PigStorage(',') AS (country_code:chararray, country_name:chararray);
B = FILTER A BY country_code == '$ACTIVE_VALUES';
dump B;
输入:a.csv
IN,India
US,United States
UK,United Kingdom
错误
Error before Pig is launched
----------------------------
ERROR 2997: Encountered IOException. org.apache.pig.tools.parameters.ParameterSubstitutionException: Undefined parameter : ACTIVE_VALUES
java.io.IOException: org.apache.pig.tools.parameters.ParameterSubstitutionException: Undefined parameter : ACTIVE_VALUES
at org.apache.pig.impl.PigContext.doParamSubstitution(PigContext.java:414)
at org.apache.pig.Main.runParamPreprocessor(Main.java:810)
at org.apache.pig.Main.run(Main.java:588)
at org.apache.pig.Main.main(Main.java:170)
Caused by: org.apache.pig.tools.parameters.ParameterSubstitutionException: Undefined parameter : ACTIVE_VALUES
at org.apache.pig.tools.parameters.PreprocessorContext.substitute(PreprocessorContext.java:355)
at org.apache.pig.tools.parameters.PreprocessorContext.substitute(PreprocessorContext.java:303)
at org.apache.pig.tools.parameters.PigFileParser.input(PigFileParser.java:67)
at org.apache.pig.tools.parameters.PigFileParser.Parse(PigFileParser.java:43)
at org.apache.pig.tools.parameters.ParameterSubstitutionPreprocessor.parsePigFile(ParameterSubstitutionPreprocessor.java:95)
at org.apache.pig.tools.parameters.ParameterSubstitutionPreprocessor.genSubstitutedFile(ParameterSubstitutionPreprocessor.java:76)
at org.apache.pig.impl.PigContext.doParamSubstitution(PigContext.java:410)
... 3 more
我对IMPORT的理解是导入的猪的内容将被执行并可以从调用猪脚本中获得。如果是这种情况,则声明的参数应该在导入猪文件中可用。
关于拥有一个常见的pig脚本文件的任何输入/想法,该文件将声明常量并在其他pig文件中导入它以实现代码模块化。
更新:
此问题已经引发了JIRA问题。参考。以下链接了解详情
答案 0 :(得分:3)
IMPORT
关键字用于导入宏,而不是常量。 %declare
和%default
是预处理程序语句,其范围是脚本中的所有剩余行。如果您在脚本中声明它,但从另一个脚本中导入它,则它将无效,因为它超出了范围。
两个语句在宏中都有效,只要您在宏中使用声明的变量即可。如果需要在脚本外部定义常量以实现模块化,则需要使用parameter file:
ACTIVE_VALUES = 'UK'
然后运行您的Pig脚本,如下所示:
pig -param_file your_params_file.properties -f your_script.pig
如果你真的想使用IMPORT
,你可以创建一个宏来处理使用该常量值的过滤:
%declare ACTIVE_VALUES 'UK';
DEFINE my_custom_filter(A) RETURNS B {
$B = FILTER $A BY $0 == '$ACTIVE_VALUES ';
};
然后像在脚本中那样导入它,但不是调用FILTER
函数,而是调用自己的宏:
IMPORT 'macro.pig';
A = LOAD 'a.csv' using PigStorage(',') AS (country_code:chararray, country_name:chararray);
B = my_custom_filter(A);
dump B;
答案 1 :(得分:1)
虽然是hackish,但另一种可能的解决方案是使用python控制器,并在该python控制器中连接两个文件。您可以阅读有关控制器here的信息。
这可能是它看起来的样子,并且会至少破坏你当前的结构:
#!/usr/bin/python
from org.apache.pig.scripting import Pig
def readfile(f):
out = []
with open(f, 'r') as infile:
for line in infile:
out.append(file)
return out
constants = readfile('constants.pig')
script = readfile('a.pig')
# Compile
P = Pig.compile('\n'.join(constants + scripts))
# Run
result = P.bind({}).runSingle()
但是,您也可以尝试在字典中传递要更改的变量,该字典是bind
方法的参数。这与使用parameter substitution的过程相同,我建议这样做。