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

Importing a common constant declared pig file in other pig files

Objective :在 constants.pig 中定义了常量(%declare 和 %default)语句以实现代码模块化并在其他 pig 文件中导入相同的语句.

根据文档:http://pig.apache.org/docs/r0.12.0/cont.html#import-macros,%declare 和 %default 是宏中的有效语句。

面临的问题: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 脚本中获得。如果是这种情况,声明的参数应该在导入猪文件中可用。

任何关于拥有一个通用 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

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 [=12=] == '$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;

虽然有点老套,但另一种可能的解决方案是使用 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 的过程相同,我建议这样做。