在其他pig文件中导入公共常量声明的pig文件

时间:2015-05-21 00:31:37

标签: import macros apache-pig

目标:在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问题。参考。以下链接了解详情

  1. https://issues.apache.org/jira/browse/PIG-2469?jql=text%20~%20%22macro%20%25default%22
  2. http://grokbase.com/t/pig/user/121c685c55/error-using-define-in-a-macro
  3. http://mail-archives.apache.org/mod_mbox/pig-user/201201.mbox/%3CCAB-acjN+hNAZn3Aws5usHW+At9rk=oFtyb26GxvKxBkjYNAODg@mail.gmail.com%3E

2 个答案:

答案 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的过程相同,我建议这样做。