【问题标题】:TypeError: got an unexpected keyword argumentTypeError:得到了一个意外的关键字参数
【发布时间】:2016-09-17 18:06:57
【问题描述】:

下面看似简单的代码抛出如下错误:

Traceback (most recent call last):
  File "/home/nirmal/process.py", line 165, in <module>
    'time_diff': f.last(adf['time_diff']).over(window_device_rows)
TypeError: __call__() got an unexpected keyword argument 'this_campaign'

代码:

# Function to flag network timeouts
def flag_network_timeout(**kwargs):
    if kwargs['this_network'] != kwargs['last_network'] \
            or kwargs['this_campaign'] != kwargs['last_campaign'] \
            or kwargs['this_adgroup'] != kwargs['last_adgroup'] \
            or kwargs['this_creative'] != kwargs['last_creative'] \
            or kwargs['time_diff'] > network_timeout:
        return 1
    else:
        return 0
flag_network_timeout = f.udf(flag_network_timeout, IntegerType())

# Column spec to go over the device events and flag network resets
network_timeout_flag = flag_network_timeout(**{
    'last_network': f.first(adf['network']).over(window_device_rows),
    'last_campaign': f.first(adf['campaign']).over(window_device_rows),
    'last_adgroup': f.first(adf['adgroup']).over(window_device_rows),
    'last_creative': f.first(adf['creative']).over(window_device_rows),
    'this_network': f.last(adf['network']).over(window_device_rows),
    'this_campaign': f.last(adf['campaign']).over(window_device_rows),
    'this_adgroup': f.last(adf['adgroup']).over(window_device_rows),
    'this_creative': f.last(adf['creative']).over(window_device_rows),
    'time_diff': f.last(adf['time_diff']).over(window_device_rows)
})

# Update dataframe with the new columns
adf = adf.select('*', network_timeout_flag.alias('network_timeout'))

请问我做错了什么?谢谢。

【问题讨论】:

  • 对于投票结束这个问题的人,想解释一下这太宽泛了吗?错误是特定的,代码是特定于错误的。
  • 结构不佳的问题 - 不易搜索
  • @muon 怎么样?标签说定义了所有语言。标题包含确切的错误消息。身体包含问题。这绝对不能保证关闭。

标签: python apache-spark pyspark apache-spark-sql user-defined-functions


【解决方案1】:

您会遇到异常,因为 UserDefinedFunction.__call__ 仅支持可变参数而不支持关键字参数。

def __call__(self, *cols):
    sc = SparkContext._active_spark_context
    jc = self._judf.apply(_to_seq(sc, cols, _to_java_column))
    return Column(jc)

在更基本的级别上,UDF 只能接收 Column 参数,这些参数将在运行时扩展为相应的值,而不是标准 Python 对象。

我个人根本不会为此使用**kwargs,但忽略了您可以通过编写SQL表达式来实现您想要的:

def flag_network_timeout_(**kwargs):

    cond = (
        (kwargs['this_network'] != kwargs['last_network']) |
        (kwargs['this_campaign'] != kwargs['last_campaign']) |
        (kwargs['this_adgroup'] != kwargs['last_adgroup']) |
        (kwargs['this_creative'] != kwargs['last_creative']) |
        (kwargs['time_diff'] > network_timeout))

    return f.when(cond, 1).otherwise(0)

【讨论】:

  • “因为 UserDefinedFunction.__call__ 仅支持可变参数而不支持关键字参数”。谢谢你。就是这样!我不认为我自己会捕捉到它。
  • 第二部分更为重要,恕我直言 :) 每当您可以在 UDF 和编写 SQL 表达式之间进行选择时,前者应该始终是您的首选。 UDF,尤其是 Python 的,有很多丑陋的属性。
  • 老实说,我没有得到第二部分。它与 UDF 有何不同?
  • 这太棒了!我将所有 UDF 转换为 SQL 表达式,最终性能提高了 22%(脚本完成从 44 分钟到 34 分钟)。感谢您的帮助!
  • 感谢指出supports only varargs and not keyword args.
猜你喜欢
  • 2012-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-08
  • 2020-11-16
  • 2021-01-03
相关资源
最近更新 更多