Python函数上的Spark UDF

时间:2019-11-25 11:16:50

标签: python pyspark databricks

我创建了一个python函数,用于使用GCP Translate API翻译短字符串。这些代码会执行以下操作。

def translateString(inputString, targetLanguage, apiKey):
    baseUrl = "https://translation.googleapis.com/language/translate/v2?key="
    q = "&q="
    gcpKey = apiKey
    target = "&target="
    sentence = str(inputString)

    #Finialize request url
    url = baseUrl + gcpKey + q + sentence + target

    #SEND REQUEST WITH EXPONENTIAL BACK OFF IN CASE OF ERRORS OF EXCEEDING QUOTA LIMITATIONS API
    session = requests.Session()        
    retry = Retry(connect=3, backoff_factor=100)
    adapter = HTTPAdapter(max_retries=retry)
    session.mount('http://', adapter)
    session.mount('https://', adapter)
    respons = session.get(url, timeout=120)

    if respons.status_code == 200:
      data = respons.json()       
      translatedStr = data["data"]["translations"][0]["translatedText"]
      returnString = str(translatedStr)
      return(returnString)

    else:
      return("Error with code: " + str(respons.status_code))

udfTrans = F.udf(translateString, StringType())

apiKey = *********

dfTempNo = dfToProcess.withColumn("TRANSLATED_FIELD", udfTrans(lit(dfToProcess.FIELD_TO_PROCESS), lit("no"), lit(apiKey)))

当遍历pd.DataFrame并在我们进行操作时存储返回变量时,这非常有用!但是现在我需要在spark.DataFrame上应用此函数,以便可以分配工作并创建了以下udfTrans = F.udf(translateString, StringType()),以便可以将其应用于string中的spark.DataFrame列。

当我在 dfTempNo = dfToProcess.withColumn("TRANSLATED_FIELD", udfTrans(lit(dfToProcess.FIELD_TO_PROCESS), lit("no"), lit(apiKey))) 它不会返回任何错误,但要花多长时间才能在dfToProcess上运行多行。

我不确定是否误解了将UDF应用于spark.DataFrame中的列。甚至有可能使用UDF将这样的功能应用于spark.DataFrame还是在Python / Pandas中这样做更好?

1 个答案:

答案 0 :(得分:2)

Python udf不能像这样并行化,因为您的executor需要回调driver来执行udf。不幸的是,这意味着您的udf将针对每一行进行阻塞,并且在执行时实质上是串行的。

使用不同的方法可以更有效地解决此问题。由于您的功能受到大量IO限制(更具体地讲是受网络限制),因此您可以查看类似ThreadPool的实现,将输出存储在Dict中,然后在{{1 }},然后从那里去。

或者,您可以在SparkContext.parallelize()中编写Dict,因为它将在执行时自动并行。

或者,看看https://spark.apache.org/docs/2.4.3/api/python/pyspark.sql.html#pyspark.sql.functions.pandas_udf 因为udf scala可以向量化。希望这会有所帮助!