我创建了一个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中这样做更好?
答案 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
可以向量化。希望这会有所帮助!