Snowpark Migration Accelerator : Codes de problème pour Python

SPRKPY1089

Message : Les valeurs de pyspark.sql.readwriter.DataFrameWriter.options dans Snowpark peuvent être différentes. Une validation obligatoire peut donc être nécessaire.

Catégorie : Avertissement

Description

Les valeurs de pyspark.sql.readwriter.DataFrameWriter.options dans Snowpark peuvent être différentes, une validation peut donc être nécessaire pour s’assurer que le comportement est correct.

Scénarios

Il existe plusieurs scénarios, selon que les options sont prises en charge ou non, ou selon le format utilisé pour écrire le fichier.

Scénario 1

Entrée

Vous trouverez ci-dessous un exemple d’utilisation des options de la méthode, en ajoutant les options sep et nullValue, qui sont actuellement prises en charge.

df = spark.createDataFrame([(1, "myVal")], [2, "myVal2"], [None, "myVal3" ])

df.write.options(nullValue="myVal", sep=",").csv("some_path")
Copy

Sortie

L’outil ajoute l’EWI SPRKPY1089 indiquant qu’il s’agit d’une validation obligatoire.

df = spark.createDataFrame([(1, "myVal")], [2, "myVal2"], [None, "myVal3" ])
#EWI: SPRKPY1089 => The pyspark.sql.readwriter.DataFrameWriter.options values in Snowpark may be different, so required validation might be needed.
df.write.options(nullValue="myVal", sep=",").csv("some_path")
Copy

Correction recommandée

L’API Snowpark prend en charge ces paramètres, la seule action possible est donc de vérifier le comportement après la migration. Veuillez vous référer à la table des équivalences pour connaître les paramètres pris en charge.

df = spark.createDataFrame([(1, "myVal")], [2, "myVal2"], [None, "myVal3" ])
#EWI: SPRKPY1089 => The pyspark.sql.readwriter.DataFrameWriter.options values in Snowpark may be different, so required validation might be needed.
df.write.options(nullValue="myVal", sep=",").csv("some_path")
Copy
Scénario 2

Entrée

Ici, le scénario montre l’utilisation des options, mais ajoute une option en-tête, qui n’est pas prise en charge.

df = spark.createDataFrame([(1, "myVal")], [2, "myVal2"], [None, "myVal3" ])

df.write.options(header=True, sep=",").csv("some_path")
Copy

Sortie

L’outil ajoute l’EWI SPRKPY1089 indiquant qu’il s’agit d’une validation obligatoire.

df = spark.createDataFrame([(1, "myVal")], [2, "myVal2"], [None, "myVal3" ])
#EWI: SPRKPY1089 => The pyspark.sql.readwriter.DataFrameWriter.options values in Snowpark may be different, so required validation might be needed.
df.write.options(header=True, sep=",").csv("some_path")
Copy

Correction recommandée

Pour ce scénario, il est recommandé d’évaluer les options du type de format Snowpark pour voir s’il est possible de le modifier en fonction de vos besoins. Vérifiez également le comportement après la modification.

df = spark.createDataFrame([(1, "myVal")], [2, "myVal2"], [None, "myVal3" ])
#EWI: SPRKPY1089 => The pyspark.sql.readwriter.DataFrameWriter.options values in Snowpark may be different, so required validation might be needed.
df.write.csv("some_path")
Copy
Scénario 3

Entrée

Ce scénario ajoute une option sep, qui est prise en charge et utilise la méthode JSON.

df = spark.createDataFrame([(1, "myVal")], [2, "myVal2"], [None, "myVal3" ])

df.write.options(nullValue="myVal", sep=",").json("some_path")
Copy

Sortie

L’outil ajoute l’EWI SPRKPY1089 indiquant qu’il s’agit d’une validation obligatoire.

  • Remarque : ce scénario s’applique également à PARQUET.

df = spark.createDataFrame([(1, "myVal")], [2, "myVal2"], [None, "myVal3" ])
#EWI: SPRKPY1089 => The pyspark.sql.readwriter.DataFrameWriter.options values in Snowpark may be different, so required validation might be needed.
df.write.options(nullValue="myVal", sep=",").json("some_path")
Copy

Correction recommandée

Le format de fichier JSON ne prend pas en charge le paramètre sep, il est donc recommandé d’évaluer les options du type de format Snowpark pour voir s’il est possible de le modifier en fonction de vos besoins. Vérifiez également le comportement après la modification.

df = spark.createDataFrame([(1, "myVal")], [2, "myVal2"], [None, "myVal3" ])
#EWI: SPRKPY1089 => The pyspark.sql.readwriter.DataFrameWriter.options values in Snowpark may be different, so required validation might be needed.
df.write.json("some_path")
Copy

Recommandations supplémentaires

  • Étant donné que certains paramètres ne sont pas pris en charge, il est recommandé de consulter la table des équivalences et de vérifier le comportement après la transformation.

  • Table des équivalences :

Snowpark peut prendre en charge une liste d”équivalences pour certains paramètres :

Option PySpark

Option SnowFlake

Formats de fichier pris en charge

Description

SEP

FIELD_DELIMITER

CSV

Un ou plusieurs caractères d’un octet ou de plusieurs octets qui séparent les champs d’un fichier d’entrée.

LINESEP

RECORD_DELIMITER

CSV

Un ou plusieurs caractères qui séparent les enregistrements dans un fichier d’entrée.

QUOTE

FIELD_OPTIONALLY_ENCLOSED_BY

CSV

Caractère utilisé pour délimiter des chaînes.

NULLVALUE

NULL_IF

CSV

Chaîne utilisée pour les conversions entrante et sortante de SQL NULL.

DATEFORMAT

DATE_FORMAT

CSV

Chaîne qui définit le format des valeurs de date dans les fichiers de données à charger.

TIMESTAMPFORMAT

TIMESTAMP_FORMAT

CSV

Chaîne qui définit le format des valeurs d’horodatage dans les fichiers de données à charger.

Si le paramètre utilisé ne figure pas dans la liste, l’API génère une erreur.

SPRKPY1088

Message : Les valeurs de pyspark.sql.readwriter.DataFrameWriter.option dans Snowpark peuvent être différentes. Une validation obligatoire peut donc être nécessaire.

Catégorie : Avertissement

Description

Les valeurs de pyspark.sql.readwriter.DataFrameWriter.option dans Snowpark peuvent être différentes, une validation peut donc être nécessaire pour s’assurer que le comportement est correct.

Scénarios

Il existe plusieurs scénarios, selon que les options sont prises en charge ou non, ou selon le format utilisé pour écrire le fichier.

Scénario 1

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de l’option de la méthode, en ajoutant l’option sep, qui est actuellement prise en charge.

df = spark.createDataFrame([(100, "myVal")], ["ID", "Value"])

df.write.option("sep", ",").csv("some_path")
Copy

Sortie

L’outil ajoute l’EWI SPRKPY1088 indiquant qu’il s’agit d’une validation obligatoire.

df = spark.createDataFrame([(100, "myVal")], ["ID", "Value"])
#EWI: SPRKPY1088 => The pyspark.sql.readwriter.DataFrameWriter.option values in Snowpark may be different, so required validation might be needed.
df.write.option("sep", ",").csv("some_path")
Copy

Correction recommandée

L’API Snowpark prend en charge ce paramètre, la seule action possible est donc de vérifier le comportement après la migration. Veuillez vous référer à la table des équivalences pour connaître les paramètres pris en charge.

df = spark.createDataFrame([(100, "myVal")], ["ID", "Value"])
#EWI: SPRKPY1088 => The pyspark.sql.readwriter.DataFrameWriter.option values in Snowpark may be different, so required validation might be needed.
df.write.option("sep", ",").csv("some_path")
Copy
Scénario 2

Entrée

Ici, le scénario montre l’utilisation de l’option, mais ajoute une option en-tête, qui n’est pas prise en charge.

df = spark.createDataFrame([(100, "myVal")], ["ID", "Value"])

df.write.option("header", True).csv("some_path")
Copy

Sortie

L’outil ajoute l’EWI SPRKPY1088 indiquant qu’il s’agit d’une validation obligatoire.

df = spark.createDataFrame([(100, "myVal")], ["ID", "Value"])
#EWI: SPRKPY1088 => The pyspark.sql.readwriter.DataFrameWriter.option values in Snowpark may be different, so required validation might be needed.
df.write.option("header", True).csv("some_path")
Copy

Correction recommandée

Pour ce scénario, il est recommandé d’évaluer les options du type de format Snowpark pour voir s’il est possible de le modifier en fonction de vos besoins. Vérifiez également le comportement après la modification.

df = spark.createDataFrame([(100, "myVal")], ["ID", "Value"])
#EWI: SPRKPY1088 => The pyspark.sql.readwriter.DataFrameWriter.option values in Snowpark may be different, so required validation might be needed.
df.write.csv("some_path")
Copy
Scénario 3

Entrée

Ce scénario ajoute une option sep, qui est prise en charge et utilise la méthode JSON.

  • Remarque : ce scénario s’applique également à PARQUET.

df = spark.createDataFrame([(100, "myVal")], ["ID", "Value"])

df.write.option("sep", ",").json("some_path")
Copy

Sortie

L’outil ajoute l’EWI SPRKPY1088 indiquant qu’il s’agit d’une validation obligatoire.

df = spark.createDataFrame([(100, "myVal")], ["ID", "Value"])
#EWI: SPRKPY1088 => The pyspark.sql.readwriter.DataFrameWriter.option values in Snowpark may be different, so required validation might be needed.
df.write.option("sep", ",").json("some_path")
Copy

Correction recommandée

Le format de fichier JSON ne prend pas en charge le paramètre sep, il est donc recommandé d’évaluer les options du type de format Snowpark pour voir s’il est possible de le modifier en fonction de vos besoins. Vérifiez également le comportement après la modification.

df = spark.createDataFrame([(100, "myVal")], ["ID", "Value"])
#EWI: SPRKPY1088 => The pyspark.sql.readwriter.DataFrameWriter.option values in Snowpark may be different, so required validation might be needed.
df.write.json("some_path")
Copy

Recommandations supplémentaires

  • Étant donné que certains paramètres ne sont pas pris en charge, il est recommandé de consulter la table des équivalences et de vérifier le comportement après la transformation.

  • Table des équivalences :

Option PySpark

Option SnowFlake

Formats de fichier pris en charge

Description

SEP

FIELD_DELIMITER

CSV

Un ou plusieurs caractères d’un octet ou de plusieurs octets qui séparent les champs d’un fichier d’entrée.

LINESEP

RECORD_DELIMITER

CSV

Un ou plusieurs caractères qui séparent les enregistrements dans un fichier d’entrée.

QUOTE

FIELD_OPTIONALLY_ENCLOSED_BY

CSV

Caractère utilisé pour délimiter des chaînes.

NULLVALUE

NULL_IF

CSV

Chaîne utilisée pour les conversions entrante et sortante de SQL NULL.

DATEFORMAT

DATE_FORMAT

CSV

Chaîne qui définit le format des valeurs de date dans les fichiers de données à charger.

TIMESTAMPFORMAT

TIMESTAMP_FORMAT

CSV

Chaîne qui définit le format des valeurs d’horodatage dans les fichiers de données à charger.

Si le paramètre utilisé ne figure pas dans la liste, l’API génère une erreur.

SPRKPY1011

Message : pyspark.sql.dataframe.DataFrameStatFunctions.approxQuantile a une solution de contournement

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.dataframe.DataFrameStatFunctions.approxQuantile qui dispose d’une solution de contournement.

Scénario

Entrée

Il est important de comprendre que Pyspark utilise deux fonctions approxQuantile différentes, nous utilisons ici la version DataFrameStatFunctions approxQuantile.

import tempfile
from pyspark.sql import SparkSession, DataFrameStatFunctions
spark = SparkSession.builder.getOrCreate()
data = [['Q1', 300000],
        ['Q2', 60000],
        ['Q3', 500002],
        ['Q4', 130000]]

columns = ['Quarter', 'Gain']
df = spark.createDataFrame(data, columns)
aprox_quantille = DataFrameStatFunctions(df).approxQuantile('Gain', [0.25, 0.5, 0.75], 0)
print(aprox_quantille)
Copy

Sortie

SMA renvoie l’EWI SPRKPY1011 sur la ligne où approxQuantile est utilisé, ce qui vous permet d’identifier l’endroit à corriger.

import tempfile
from snowflake.snowpark import Session, DataFrameStatFunctions
spark = Session.builder.getOrCreate()
spark.update_query_tag({"origin":"sf_sit","name":"sma","version":{"major":0,"minor":0,"patch":0},"attributes":{"language":"Python"}})
data = [['Q1', 300000],
        ['Q2', 60000],
        ['Q3', 500002],
        ['Q4', 130000]]

columns = ['Quarter', 'Gain']
df = spark.createDataFrame(data, columns)
#EWI: SPRKPY1011 => pyspark.sql.dataframe.DataFrameStatFunctions.approxQuantile has a workaround, see documentation for more info
aprox_quantille = DataFrameStatFunctions(df).approxQuantile('Gain', [0.25, 0.5, 0.75], 0)
Copy

Correction recommandée

Vous pouvez utiliser la méthode approxQuantile Snowpark. Certains paramètres ne correspondent pas et nécessitent donc des corrections manuelles. Pour l’exemple du code de sortie, la correction recommandée pourrait être la suivante :

from snowflake.snowpark import Session # remove DataFrameStatFunctions because is not required
...
df = spark.createDataFrame(data, columns)

aprox_quantille = df.stat.approx_quantile('Ammount', [0.25, 0.5, 0.75])
Copy

Le paramètre d’erreur relatif à pyspark.sql.dataframe.DataFrame.approxQuantile n’existe pas dans SnowPark.

Recommandations supplémentaires

SPRKPY1040

Avertissement

Ce code de problème est maintenant obsolète.

Message : pyspark.sql.functions.explode a une solution de contournement. Voir la documentation pour plus d’informations

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil SMA détecte une utilisation de la fonction pyspark.sql.functions.explode, qui dispose d’une solution de contournement.

Scénario

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de la fonction pyspark.sql.functions.explode qui génère cet EWI. Dans cet exemple, la fonction explode est utilisée pour générer une ligne par élément du tableau pour la colonne numbers.

df = spark.createDataFrame([("Alice", [1, 2, 3]), ("Bob", [4, 5]), ("Charlie", [6, 7, 8, 9])], ["name", "numbers"])
exploded_df = df.select("name", explode(df.numbers).alias("number"))
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1040 au code de sortie pour vous indiquer que cette fonction n’est pas directement prise en charge par Snowpark, mais qu’il existe une solution de contournement.

df = spark.createDataFrame([("Alice", [1, 2, 3]), ("Bob", [4, 5]), ("Charlie", [6, 7, 8, 9])], ["name", "numbers"])
#EWI: SPRKPY1040 => pyspark.sql.functions.explode has a workaround, see documentation for more info
exploded_df = df.select("name", explode(df.numbers).alias("number"))
Copy

Correction recommandée

Pour contourner le problème, vous pouvez importer le paquet snowpark_extensions qui fournit une extension pour la fonction explode.

import snowpark_extensions

df = spark.createDataFrame([("Alice", [1, 2, 3]), ("Bob", [4, 5]), ("Charlie", [6, 7, 8, 9])], ["name", "numbers"])
exploded_df = df.select("name", explode(df.numbers).alias("number"))
Copy

Recommandations supplémentaires

SPRKPY1074

Message : Le fichier a une indentation mixte (espaces et tabulations).

Catégorie : Erreur d’analyse.

Description

Ce problème apparaît lorsque l’outil détecte que le fichier a une indentation mixte. Cela signifie que le fichier comporte une combinaison d’espaces et de tabulations pour indenter les lignes de code.

Scénario

Entrée

Dans Pyspark, vous pouvez mélanger les espaces et les tabulations pour le niveau d’indentation.

def foo():
    x = 5 # spaces
    y = 6 # tab
Copy

Sortie

SMA ne peut pas gérer les marqueurs d’indentation mixtes. Lorsque cela est détecté sur un fichier de code Python, l’outil SMA ajoute l’EWI SPRKPY1074 sur la première ligne.

## EWI: SPRKPY1074 => File has mixed indentation (spaces and tabs).
## This file was not converted, so it is expected to still have references to the Spark API
def foo():
    x = 5 # spaces
    y = 6 # tabs
Copy

Correction recommandée

La solution est de rendre tous les symboles d’indentation identiques.

def foo():
  x = 5 # tab
  y = 6 # tab
Copy

Recommandations supplémentaires

SPRKPY1025

Avertissement

Ce code de problème est maintenant obsolète.

Message : pyspark.sql.functions.ntile a une solution de contournement. Voir la documentation pour plus d’informations

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil SMA détecte une utilisation de la fonction pyspark.sql.functions.ntile, qui dispose d’une solution de contournement.

Scénario

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de la fonction pyspark.sql.functions.ntile qui génère cet EWI. Dans cet exemple, la fonction ntile est utilisée pour diviser les lignes en 3 compartiments.

df = spark.createDataFrame([("Alice", 50), ("Bob", 30), ("Charlie", 60), ("David", 90), ("Eve", 70), ("Frank", 40)], ["name", "score"])
windowSpec = Window.orderBy("score")
df_with_ntile = df.withColumn("bucket", ntile(3).over(windowSpec))
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1025 au code de sortie pour vous indiquer que cette fonction n’est pas directement prise en charge par Snowpark, mais qu’il existe une solution de contournement.

df = spark.createDataFrame([("Alice", 50), ("Bob", 30), ("Charlie", 60), ("David", 90), ("Eve", 70), ("Frank", 40)], ["name", "score"])
windowSpec = Window.orderBy("score")
#EWI: SPRKPY1025 => pyspark.sql.functions.ntile has a workaround, see documentation for more info
df_with_ntile = df.withColumn("bucket", ntile(3).over(windowSpec))
Copy

Correction recommandée

Snowpark dispose d’une fonction ntile équivalente, mais l’argument qui lui est transmis doit être une colonne. Pour contourner le problème, vous pouvez convertir l’argument littéral en colonne à l’aide de la fonction snowflake.snowpark.functions.lit.

df = spark.createDataFrame([("Alice", 50), ("Bob", 30), ("Charlie", 60), ("David", 90), ("Eve", 70), ("Frank", 40)], ["name", "score"])
windowSpec = Window.orderBy("score")
df_with_ntile = df.withColumn("bucket", ntile(lit(3)).over(windowSpec))
Copy

Recommandations supplémentaires

SPRKPY1087

Message : La fonction pyspark.sql.dataframe.DataFrame.writeTo n’est pas prise en charge, mais une solution de contournement existe.

Catégorie : Avertissement

Description

La fonction pyspark.sql.dataframe.DataFrame.writeTo n’est pas prise en charge. La solution consiste à utiliser la méthode Snowpark DataFrameWriter SaveAsTable à la place.

Scénario

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de la fonction pyspark.sql.dataframe.DataFrame.writeTo, le dataframe df est écrit dans une table nommée Personal_info.

df = spark.createDataFrame([["John", "Berry"], ["Rick", "Berry"], ["Anthony", "Davis"]],
                                 schema=["FIRST_NAME", "LAST_NAME"])

df.writeTo("Personal_info")
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1087 au code de sortie pour vous indiquer que cette fonction n’est pas prise en charge, mais qu’il existe une solution de contournement.

df = spark.createDataFrame([["John", "Berry"], ["Rick", "Berry"], ["Anthony", "Davis"]],
                                 schema=["FIRST_NAME", "LAST_NAME"])

#EWI: SPRKPY1087 => pyspark.sql.dataframe.DataFrame.writeTo is not supported, but it has a workaround.
df.writeTo("Personal_info")
Copy

Correction recommandée

La solution consiste à utiliser la méthode Snowpark DataFrameWriter SaveAsTable à la place.

df = spark.createDataFrame([["John", "Berry"], ["Rick", "Berry"], ["Anthony", "Davis"]],
                                 schema=["FIRST_NAME", "LAST_NAME"])

df.write.saveAsTable("Personal_info")
Copy

Recommandations supplémentaires

SPRKPY1035

Avertissement

Ce code de problème est maintenant obsolète.

Message : pyspark.sql.functions.reverse a une solution de contournement. Voir la documentation pour plus d’informations

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil SMA détecte une utilisation de la fonction pyspark.sql.functions.reverse, qui dispose d’une solution de contournement.

Scénario

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de la fonction pyspark.sql.functions.reverse qui génère cet EWI. Dans cet exemple, la fonction reverse est utilisée pour inverser chaque chaîne de la colonne word.

df = spark.createDataFrame([("hello",), ("world",)], ["word"])
df_reversed = df.withColumn("reversed_word", reverse(df["word"]))
df_reversed = df.withColumn("reversed_word", reverse("word"))
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1035 au code de sortie pour vous indiquer que cette fonction n’est pas directement prise en charge par Snowpark, mais qu’il existe une solution de contournement.

df = spark.createDataFrame([("hello",), ("world",)], ["word"])
#EWI: SPRKPY1035 => pyspark.sql.functions.reverse has a workaround, see documentation for more info
df_reversed = df.withColumn("reversed_word", reverse(df["word"]))
#EWI: SPRKPY1035 => pyspark.sql.functions.reverse has a workaround, see documentation for more info
df_reversed = df.withColumn("reversed_word", reverse("word"))
Copy

Correction recommandée

Pour contourner le problème, vous pouvez importer le paquet snowpark_extensions qui fournit une extension pour la fonction reverse.

import snowpark_extensions

df = spark.createDataFrame([("hello",), ("world",)], ["word"])
df_reversed = df.withColumn("reversed_word", reverse(df["word"]))
df_reversed = df.withColumn("reversed_word", reverse("word"))
Copy

Recommandations supplémentaires

SPRKPY1064

Message : L’élément _ Spark _ ne s’applique pas car Snowflake utilise plutôt le mécanisme Snowpipe.

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation d’un élément de la bibliothèque pyspark.streaming :

Scénario

Entrée

Vous trouverez ci-dessous un exemple avec l’un des éléments qui déclenchent cet EWI.

from pyspark.streaming.listener import StreamingListener

var = StreamingListener.Java
var.mro()

df = spark.createDataFrame([(25, "Alice", "150"), (30, "Bob", "350")], schema=["age", "name", "value"])
df.show()
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1064 au code de sortie pour vous indiquer que cette fonction ne s’applique pas.

#EWI: SPRKPY1064 => The element does not apply since snowflake uses snowpipe mechanism instead.

var = StreamingListener.Java
var.mro()

df = spark.createDataFrame([(25, "Alice", "150"), (30, "Bob", "350")], schema=["age", "name", "value"])
df.show()
Copy

Correction recommandée

L’outil SMA supprime l’instruction d’importation et ajoute le problème à l’inventaire Issues.csv, supprime toute utilisation de l’élément Spark.

df = spark.createDataFrame([(25, "Alice", "150"), (30, "Bob", "350")], schema=["age", "name", "value"])
df.show()
Copy

Recommandations supplémentaires

SPRKPY1050

Message : pyspark.conf.SparkConf.set a une solution de contournement

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.conf.SparkConf.set qui dispose d’une solution de contournement.

Scénario

Entrée

Vous trouverez ci-dessous un exemple de définition d’une variable à l’aide de conf.set.

conf = SparkConf().setAppName('my_app')

conf.set("spark.storage.memoryFraction", "0.5")
Copy

Sortie

L’outil ajoute l’EWI SPRKPY1050 indiquant qu’une solution de contournement peut être mise en œuvre.

conf = SparkConf().setAppName('my_app')

#EWI: SPRKPY1050 => pyspark.conf.SparkConf.set has a workaround, see documentation for more info
conf.set("spark.storage.memoryFraction", "0.5")
Copy

Correction recommandée

SparkConf.set est utilisé pour définir un paramètre de configuration utilisé uniquement par Pyspark et ne s’applique pas à Snowpark. Vous pouvez supprimer ou commenter le code

#conf.set("spark.storage.memoryFraction", "0.5")
Copy

Recommandations supplémentaires

SPRKPY1001

Message&#x65 ; ** :** Cette section de code contient des erreurs d’analyse

Catégorie&#x79 ; ** :** Erreur d’analyse.

Description

Une erreur d’analyse est signalée par l’outil Snowpark Migration Accelerator (SMA) lorsqu’il ne peut pas lire ou comprendre correctement le code d’un fichier (il ne peut pas « analyser » correctement le fichier). Ce code de problème apparaît lorsqu’un fichier présente une ou plusieurs erreurs d’analyse.

Scénario

Entrée : Le message EWI apparaît lorsque le code présente une syntaxe non valide, par exemple :

def foo():
    x = %%%%%%1###1
Copy

Sortie : SMA détecte une erreur d’analyse et commente l’erreur d’analyse en ajoutant le message EWI correspondant :

def foo():
    x
## EWI: SPRKPY1101 => Unrecognized or invalid CODE STATEMENT @(2, 7). Last valid token was 'x' @(2, 5), failed token '=' @(2, 7)
##      = %%%%%%1###1
Copy

Recommandations supplémentaires

  • Vérifiez que le fichier contient un code Python valide. (Vous pouvez utiliser le fichier issues.csv pour trouver tous les fichiers avec ce code EWI afin de déterminer quel(s) fichier(s) n’a/ont pas été traité(s) par l’outil en raison d’une/des erreur(s) d’analyse) De nombreuses erreurs d’analyse se produisent car une partie seulement du code est saisie dans l’outil. Il est donc préférable de s’assurer que le code sera exécuté dans la source. S’il est valide, signalez que vous avez rencontré une erreur d’analyse en utilisant l’option Signaler un problème dans SMA. Incluez la ligne de code à l’origine de l’erreur d’analyse dans la description lorsque vous déclarez ce problème.

  • Pour plus d’assistance, vous pouvez nous envoyer un e-mail à sma-support@snowflake.com ou signaler un problème dans l’outil SMA.

SPRKPY1021

Avertissement

Ce code de problème est maintenant obsolète.

Message : pyspark.sql.functions.last a une solution de contournement. Voir la documentation pour plus d’informations

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil SMA détecte une utilisation de la fonction pyspark.sql.functions.last, qui dispose d’une solution de contournement.

Scénario

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de la fonction pyspark.sql.functions.last qui génère cet EWI. Dans cet exemple, la fonction last est utilisée pour obtenir la dernière valeur pour chaque nom.

df = spark.createDataFrame([("Alice", 1), ("Bob", 2), ("Charlie", 3), ("Alice", 4), ("Bob", 5)], ["name", "value"])
df_grouped = df.groupBy("name").agg(last("value").alias("last_value"))
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1021 au code de sortie pour vous indiquer que cette fonction n’est pas directement prise en charge par Snowpark, mais qu’il existe une solution de contournement.

df = spark.createDataFrame([("Alice", 1), ("Bob", 2), ("Charlie", 3), ("Alice", 4), ("Bob", 5)], ["name", "value"])
#EWI: SPRKPY1021 => pyspark.sql.functions.last has a workaround, see documentation for more info
df_grouped = df.groupBy("name").agg(last("value").alias("last_value"))
Copy

Correction recommandée

Pour contourner le problème, vous pouvez utiliser la fonction LAST_VALUE Snowflake . Pour appeler cette fonction à partir de Snowpark, utilisez la fonction snowflake.snowpark.functions.call_builtin et transférez la chaîne last_value comme premier argument et la colonne correspondante comme second argument. Si vous utilisiez le nom de la colonne dans la fonction last, vous devez le convertir en colonne lorsque vous appelez la fonction call_builtin.

df = spark.createDataFrame([("Alice", 1), ("Bob", 2), ("Charlie", 3), ("Alice", 4), ("Bob", 5)], ["name", "value"])
df_grouped = df.groupBy("name").agg(call_builtin("last_value", col("value")).alias("last_value"))
Copy

Recommandations supplémentaires


description : >- Le paramètre mode dans les méthodes CSV, JSON et PARQUET est transformé en overwrite


SPRKPY1070

Message : L’argument mode est transformé en overwrite. Vérifiez la valeur de la variable et définissez la valeur booléenne correspondante.

Catégorie : Avertissement

Description

En cas d’utilisation de :

L’outil analyse le paramètre mode pour déterminer si la valeur est overwrite.

Scénarios

Scénario 1

Code d’entrée

Pour ce scénario, l’outil détecte que le paramètre mode peut définir la valeur booléenne correspondante.

df.write.csv(file_path, mode="overwrite")
Copy

Code de sortie :

L’outil SMA analyse le paramètre mode, détermine que la valeur est , écrase et définit l’ensemble la valeur booléenne correspondante.

df.write.csv(file_path, format_type_options = dict(compression = "None"), overwrite = True)
Copy

Correction recommandée

Il n’y a pas de correction recommandée pour ce scénario car l’outil a effectué la transformation correspondante.

Scénario 2 :

Code d’entrée

Dans ce scénario, l’outil ne peut pas valider que la valeur est overwrite.

df.write.csv(file_path, mode=myVal)
Copy

Code de sortie :

L’outil SMA ajoute un message EWI indiquant que le paramètre mode a été transformé en « overwrite », mais également pour vous indiquer qu’il est préférable de vérifier la valeur de la variable et de définir la valeur boolénne correcte.

#EWI: SPRKPY1070 => The 'mode' argument is transformed to 'overwrite', check the variable value and set the corresponding bool value.
df.write.csv(file_path, format_type_options = dict(compression = "None"), overwrite = myVal)
Copy

Correction recommandée

Vérifiez la valeur du paramètre mode et ajoutez la valeur correcte du paramètre overwrite.

df.write.csv(file_path, format_type_options = dict(compression = "None"), overwrite = True)
Copy

Recommandations supplémentaires

SPRKPY1083

Message : La fonction pyspark.sql.readwriter.DataFrameWriter.save n’est pas prise en charge. La solution consiste à utiliser la méthode Snowpark DataFrameWriter copy_into_location à la place.

Catégorie : Avertissement

Description

La fonction pyspark.sql.readwriter.DataFrameWriter.save n’est pas prise en charge. La solution consiste à utiliser les méthodes Snowpark DataFrameWriter à la place.

Scénarios

La signature Spark de cette méthode DataFrameWriter.save(path, format, mode, partitionBy, **options) n’existe pas dans Snowpark. Par conséquent, toute utilisation de la fonction de chargement aura pour conséquence un EWI dans le code de sortie.

Scénario 1

Code d’entrée

Vous trouverez ci-dessous un exemple qui tente d’enregistrer des données au format CSV.

path_csv_file = "/path/to/file.csv"

data = [
        ("John", 30, "New York"),
        ("Jane", 25, "San Francisco")
    ]

df = my_session.createDataFrame(data, schema=["Name", "Age", "City"])

df.write.save(path_csv_file, format="csv")
df.write.save(path_csv_file, format="csv", mode="overwrite")
df.write.save(path_csv_file, format="csv", mode="overwrite", lineSep="\r\n", dateFormat="YYYY/MM/DD")
df.write.save(path_csv_file, format="csv", mode="overwrite", partitionBy="City", lineSep="\r\n", dateFormat="YYYY/MM/DD")
Copy

Code de sortie

L’outil ajoute l’EWI SPRKPY1083 au code de sortie pour vous indiquer que cette fonction n’est pas prise en charge par Snowpark, mais qu’il existe une solution de contournement.

path_csv_file = "/path/to/file.csv"

data = [
        ("John", 30, "New York"),
        ("Jane", 25, "San Francisco")
    ]

df = my_session.createDataFrame(data, schema=["Name", "Age", "City"])

#EWI: SPRKPY1083 => The pyspark.sql.readwriter.DataFrameWriter.save function is not supported. A workaround is to use Snowpark DataFrameWriter copy_into_location method instead.
df.write.save(path_csv_file, format="csv")
#EWI: SPRKPY1083 => The pyspark.sql.readwriter.DataFrameWriter.save function is not supported. A workaround is to use Snowpark DataFrameWriter copy_into_location method instead.
df.write.save(path_csv_file, format="csv", mode="overwrite")
#EWI: SPRKPY1083 => The pyspark.sql.readwriter.DataFrameWriter.save function is not supported. A workaround is to use Snowpark DataFrameWriter copy_into_location method instead.
df.write.save(path_csv_file, format="csv", mode="overwrite", lineSep="\r\n", dateFormat="YYYY/MM/DD")
#EWI: SPRKPY1083 => The pyspark.sql.readwriter.DataFrameWriter.save function is not supported. A workaround is to use Snowpark DataFrameWriter copy_into_location method instead.
df.write.save(path_csv_file, format="csv", mode="overwrite", partitionBy="City", lineSep="\r\n", dateFormat="YYYY/MM/DD")
Copy

Correction recommandée

Pour contourner le problème, vous pouvez utiliser les méthodes Snowpark DataFrameWriter à la place.

  • Correction des paramètres path et format :

    • Remplacez la méthode load par la méthode csv ou copy_into_location.

    • Si vous utilisez la méthode copy_into_location, vous devez spécifier le format avec le paramètre file_format_type.

    • Le premier paramètre path doit être dans une zone de préparation pour présenter une équivalence avec Snowpark.

Vous trouverez ci-dessous un exemple qui crée une zone de préparation temporelle et y place le fichier, puis appelle l’une des méthodes mentionnées ci-dessus.

data = [
        ("John", 30, "New York"),
        ("Jane", 25, "San Francisco")
    ]
df = spark.createDataFrame(data, schema=["Name", "Age", "City"])

## Stage creation

temp_stage = f'{Session.get_fully_qualified_current_schema()}.{_generate_prefix("TEMP_STAGE")}'
my_session.sql(f'CREATE TEMPORARY STAGE IF NOT EXISTS {temp_stage}').show()
my_session.file.put(f"file:///path/to/file.csv", f"@{temp_stage}")
stage_file_path = f"{temp_stage}file.csv"

## Using csv method
df.write.csv(stage_file_path)

## Using copy_into_location method
df.write.copy_into_location(stage_file_path, file_format_type="csv")
Copy

Vous trouverez ci-dessous un exemple qui ajoute à la chaîne en guirlande la méthode mode avec le paramètre overwrite.

data = [
        ("John", 30, "New York"),
        ("Jane", 25, "San Francisco")
    ]
df = spark.createDataFrame(data, schema=["Name", "Age", "City"])

## Using csv method
df.write.mode("overwrite").csv(temp_stage)

## Using copy_into_location method
df.write.mode("overwrite").copy_into_location(temp_stage, file_format_type="csv")
Copy
  • Correction du paramètre partitionBy :

    • Utilisez le paramètre partition_by de la méthode CSV, comme suit :

Vous trouverez ci-dessous un exemple qui utilise le paramètre partition_by de la méthode CSV.

data = [
        ("John", 30, "New York"),
        ("Jane", 25, "San Francisco")
    ]
df = spark.createDataFrame(data, schema=["Name", "Age", "City"])

## Using csv method
df.write.csv(temp_stage, partition_by="City")

## Using copy_into_location method
df.write.copy_into_location(temp_stage, file_format_type="csv", partition_by="City")
Copy
  • Correction du paramètre options :

Les options entre Spark et Snowpark ne sont pas les mêmes. Dans ce cas, lineSep et dateFormat sont remplacés par RECORD_DELIMITER et DATE_FORMAT, la section Recommandations supplémentaires contient une table avec toutes les équivalences.

Vous trouverez ci-dessous un exemple qui crée un dictionnaire avec RECORD_DELIMITER et DATE_FORMAT, et qui appelle la méthode options avec ce dictionnaire.

data = [
        ("John", 30, "New York"),
        ("Jane", 25, "San Francisco")
    ]
df = spark.createDataFrame(data, schema=["Name", "Age", "City"])
optionsParam = {"RECORD_DELIMITER": "\r\n", "DATE_FORMAT": "YYYY/MM/DD"}

## Using csv method
df.write.csv(stage, format_type_options=optionsParam)

## Using copy_into_location method
df.write.csv(stage, file_format_type="csv", format_type_options=optionsParam)
Copy

Scénario 2

Code d’entrée

Vous trouverez ci-dessous un exemple qui tente d’enregistrer des données au format JSON.

path_json_file = "/path/to/file.json"

data = [
        ("John", 30, "New York"),
        ("Jane", 25, "San Francisco")
    ]

df = spark.createDataFrame(data, schema=["Name", "Age", "City"])

df.write.save(path_json_file, format="json")
df.write.save(path_json_file, format="json", mode="overwrite")
df.write.save(path_json_file, format="json", mode="overwrite", dateFormat="YYYY/MM/DD", timestampFormat="YYYY-MM-DD HH24:MI:SS.FF3")
df.write.save(path_json_file, format="json", mode="overwrite", partitionBy="City", dateFormat="YYYY/MM/DD", timestampFormat="YYYY-MM-DD HH24:MI:SS.FF3")
Copy

Code de sortie

L’outil ajoute l’EWI SPRKPY1083 au code de sortie pour vous indiquer que cette fonction n’est pas prise en charge par Snowpark, mais qu’il existe une solution de contournement.

path_json_file = "/path/to/file.json"

data = [
        ("John", 30, "New York"),
        ("Jane", 25, "San Francisco")
    ]

df = spark.createDataFrame(data, schema=["Name", "Age", "City"])

#EWI: SPRKPY1083 => The pyspark.sql.readwriter.DataFrameWriter.save function is not supported. A workaround is to use Snowpark DataFrameWriter copy_into_location method instead.
df.write.save(path_json_file, format="json")
#EWI: SPRKPY1083 => The pyspark.sql.readwriter.DataFrameWriter.save function is not supported. A workaround is to use Snowpark DataFrameWriter copy_into_location method instead.
df.write.save(path_json_file, format="json", mode="overwrite")
#EWI: SPRKPY1083 => The pyspark.sql.readwriter.DataFrameWriter.save function is not supported. A workaround is to use Snowpark DataFrameWriter copy_into_location method instead.
df.write.save(path_json_file, format="json", mode="overwrite", dateFormat="YYYY/MM/DD", timestampFormat="YYYY-MM-DD HH24:MI:SS.FF3")
#EWI: SPRKPY1083 => The pyspark.sql.readwriter.DataFrameWriter.save function is not supported. A workaround is to use Snowpark DataFrameWriter copy_into_location method instead.
df.write.save(path_json_file, format="json", mode="overwrite", partitionBy="City", dateFormat="YYYY/MM/DD", timestampFormat="YYYY-MM-DD HH24:MI:SS.FF3")
Copy

Correction recommandée

Pour contourner le problème, vous pouvez utiliser les méthodes Snowpark DataFrameReader à la place.

  • Correction des paramètres path et format :

    • Remplacez la méthode load par la méthode json ou copy_into_location.

    • Si vous utilisez la méthode copy_into_location, vous devez spécifier le format avec le paramètre file_format_type.

    • Le premier paramètre path doit être dans une zone de préparation pour présenter une équivalence avec Snowpark.

Vous trouverez ci-dessous un exemple qui crée une zone de préparation temporelle et y place le fichier, puis appelle l’une des méthodes mentionnées ci-dessus.

data = [
        ("John", 30, "New York"),
        ("Jane", 25, "San Francisco")
    ]
df = spark.createDataFrame(data, schema=["Name", "Age", "City"])

## Stage creation

temp_stage = f'{Session.get_fully_qualified_current_schema()}.{_generate_prefix("TEMP_STAGE")}'
my_session.sql(f'CREATE TEMPORARY STAGE IF NOT EXISTS {temp_stage}').show()
my_session.file.put(f"file:///path/to/file.json", f"@{temp_stage}")
stage_file_path = f"{temp_stage}file.json"

## Using json method
df.write.json(stage_file_path)

## Using copy_into_location method
df.write.copy_into_location(stage_file_path, file_format_type="json")
Copy

Vous trouverez ci-dessous un exemple qui ajoute à la chaîne en guirlande la méthode mode avec le paramètre overwrite.

data = [
        ("John", 30, "New York"),
        ("Jane", 25, "San Francisco")
    ]
df = spark.createDataFrame(data, schema=["Name", "Age", "City"])

## Using json method
df.write.mode("overwrite").json(temp_stage)

## Using copy_into_location method
df.write.mode("overwrite").copy_into_location(temp_stage, file_format_type="json")
Copy
  • Correction du paramètre partitionBy :

    • Utilisez le paramètre partition_by de la méthode CSV, comme suit :

Vous trouverez ci-dessous un exemple qui utilise le paramètre partition_by de la méthode CSV.

data = [
        ("John", 30, "New York"),
        ("Jane", 25, "San Francisco")
    ]
df = spark.createDataFrame(data, schema=["Name", "Age", "City"])

## Using json method
df.write.json(temp_stage, partition_by="City")

## Using copy_into_location method
df.write.copy_into_location(temp_stage, file_format_type="json", partition_by="City")
Copy
  • Correction du paramètre options :

Les options entre Spark et Snowpark ne sont pas les mêmes. Dans ce cas, dateFormat et timestampFormat sont remplacés par DATE_FORMAT et TIMESTAMP_FORMAT, la section Recommandations supplémentaires contient une table avec toutes les équivalences.

Vous trouverez ci-dessous un exemple qui crée un dictionnaire avec DATE_FORMAT et TIMESTAMP_FORMAT, et qui appelle la méthode options avec ce dictionnaire.

data = [
        ("John", 30, "New York"),
        ("Jane", 25, "San Francisco")
    ]
df = spark.createDataFrame(data, schema=["Name", "Age", "City"])
optionsParam = {"DATE_FORMAT": "YYYY/MM/DD", "TIMESTAMP_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3"}

## Using json method
df.write.json(stage, format_type_options=optionsParam)

## Using copy_into_location method
df.write.copy_into_location(stage, file_format_type="json", format_type_options=optionsParam)
Copy

Scénario 3

Code d’entrée

Vous trouverez ci-dessous un exemple qui tente d’enregistrer des données au format PARQUET.

path_parquet_file = "/path/to/file.parquet"

data = [
        ("John", 30, "New York"),
        ("Jane", 25, "San Francisco")
    ]

df = spark.createDataFrame(data, schema=["Name", "Age", "City"])

df.write.save(path_parquet_file, format="parquet")
df.write.save(path_parquet_file, format="parquet", mode="overwrite")
df.write.save(path_parquet_file, format="parquet", mode="overwrite", pathGlobFilter="*.parquet")
df.write.save(path_parquet_file, format="parquet", mode="overwrite", partitionBy="City", pathGlobFilter="*.parquet")
Copy

Code de sortie

L’outil ajoute l’EWI SPRKPY1083 au code de sortie pour vous indiquer que cette fonction n’est pas prise en charge par Snowpark, mais qu’il existe une solution de contournement.

path_parquet_file = "/path/to/file.parquet"

data = [
        ("John", 30, "New York"),
        ("Jane", 25, "San Francisco")
    ]

df = spark.createDataFrame(data, schema=["Name", "Age", "City"])

#EWI: SPRKPY1083 => The pyspark.sql.readwriter.DataFrameWriter.save function is not supported. A workaround is to use Snowpark DataFrameWriter copy_into_location method instead.
df.write.save(path_parquet_file, format="parquet")
#EWI: SPRKPY1083 => The pyspark.sql.readwriter.DataFrameWriter.save function is not supported. A workaround is to use Snowpark DataFrameWriter copy_into_location method instead.
df.write.save(path_parquet_file, format="parquet", mode="overwrite")
#EWI: SPRKPY1083 => The pyspark.sql.readwriter.DataFrameWriter.save function is not supported. A workaround is to use Snowpark DataFrameWriter copy_into_location method instead.
df.write.save(path_parquet_file, format="parquet", mode="overwrite", pathGlobFilter="*.parquet")
#EWI: SPRKPY1083 => The pyspark.sql.readwriter.DataFrameWriter.save function is not supported. A workaround is to use Snowpark DataFrameWriter copy_into_location method instead.
df.write.save(path_parquet_file, format="parquet", mode="overwrite", partitionBy="City", pathGlobFilter="*.parquet")
Copy

Correction recommandée

Pour contourner le problème, vous pouvez utiliser les méthodes Snowpark DataFrameReader à la place.

  • Correction des paramètres path et format :

    • Remplacez la méthode load par la méthode parquet ou copy_into_location.

    • Si vous utilisez la méthode copy_into_location, vous devez spécifier le format avec le paramètre file_format_type.

    • Le premier paramètre path doit être dans une zone de préparation pour présenter une équivalence avec Snowpark.

Vous trouverez ci-dessous un exemple qui crée une zone de préparation temporelle et y place le fichier, puis appelle l’une des méthodes mentionnées ci-dessus.

data = [
        ("John", 30, "New York"),
        ("Jane", 25, "San Francisco")
    ]
df = spark.createDataFrame(data, schema=["Name", "Age", "City"])

## Stage creation

temp_stage = f'{Session.get_fully_qualified_current_schema()}.{_generate_prefix("TEMP_STAGE")}'
my_session.sql(f'CREATE TEMPORARY STAGE IF NOT EXISTS {temp_stage}').show()
my_session.file.put(f"file:///path/to/file.parquet", f"@{temp_stage}")
stage_file_path = f"{temp_stage}file.parquet"

## Using parquet method
df.write.parquet(stage_file_path)

## Using copy_into_location method
df.write.copy_into_location(stage, file_format_type="parquet")
Copy

Vous trouverez ci-dessous un exemple qui ajoute à la chaîne en guirlande la méthode mode avec le paramètre overwrite.

data = [
        ("John", 30, "New York"),
        ("Jane", 25, "San Francisco")
    ]
df = spark.createDataFrame(data, schema=["Name", "Age", "City"])

## Using parquet method
df.write.mode("overwrite").parquet(temp_stage)

## Using copy_into_location method
df.write.mode("overwrite").copy_into_location(stage, file_format_type="parquet")
Copy
  • Correction du paramètre partitionBy :

    • Utilisez le paramètre partition_by de la méthode CSV, comme suit :

Vous trouverez ci-dessous un exemple qui utilise le paramètre partition_by de la méthode parquet.

data = [
        ("John", 30, "New York"),
        ("Jane", 25, "San Francisco")
    ]
df = spark.createDataFrame(data, schema=["Name", "Age", "City"])

## Using parquet method
df.write.parquet(temp_stage, partition_by="City")

## Using copy_into_location method
df.write.copy_into_location(stage, file_format_type="parquet", partition_by="City")
Copy
  • Correction du paramètre options :

Les options entre Spark et Snowpark ne sont pas les mêmes. Dans ce cas, pathGlobFilter est remplacé par PATTERN, la section Recommandations supplémentaires contient une table avec toutes les équivalences.

Vous trouverez ci-dessous un exemple qui crée un dictionnaire avec PATTERN, et qui appelle la méthode options avec ce dictionnaire.

data = [
        ("John", 30, "New York"),
        ("Jane", 25, "San Francisco")
    ]
df = spark.createDataFrame(data, schema=["Name", "Age", "City"])
optionsParam = {"PATTERN": "*.parquet"}

## Using parquet method
df.write.parquet(stage, format_type_options=optionsParam)

## Using copy_into_location method
df.write.copy_into_location(stage, file_format_type="parquet", format_type_options=optionsParam)
Copy

Recommandations supplémentaires

  • Tenez compte du fait que les options entre Spark et Snowpark ne sont pas les mêmes, mais qu’elles peuvent être mappées :

Options Spark

Valeur possible

Équivalent Snowpark

Description

header

Vrai ou faux

SKIP_HEADER = 1 / SKIP_HEADER = 0

Pour utiliser la première ligne d’un fichier comme nom de colonne.

delimiter

Tout séparateur de champ à un ou plusieurs caractères

FIELD_DELIMITER

Pour spécifier un ou plusieurs caractères comme séparateur pour chaque colonne/champ.

sep

Tout séparateur de champ à un caractère

FIELD_DELIMITER

Pour spécifier un seul caractère comme séparateur pour chaque colonne/champ.

encoding

UTF-8, UTF-16, etc…

ENCODING

Pour décoder les fichiers CSV selon le type d’encodage donné. L’encodage par défaut est UTF-8

ligneSep

Tout séparateur de lignes à un caractère

RECORD_DELIMITER

Pour définir le séparateur de lignes à utiliser pour l’analyse du fichier.

pathGlobFilter

Modèle de fichier

PATTERN

Pour définir un modèle permettant de lire uniquement les fichiers dont les noms correspondent au modèle.

recursiveFileLookup

Vrai ou faux

N/A

Pour analyser de manière récursive un répertoire afin d’y lire des fichiers. La valeur par défaut de cette option est False.

quote

Caractère unique à mettre entre guillemets

FIELD_OPTIONALLY_ENCLOSED_BY

Permet de mettre entre guillemets les champs/colonnes contenant des champs où le délimiteur/séparateur peut faire partie de la valeur. Ce caractère permet de mettre entre guillemets tous les champs lorsqu’il est utilisé avec l’option quoteAll. La valeur par défaut de cette option est guillemet double (« ).

nullValue

Chaîne pour remplacer la valeur nulle

NULL_IF

Permet de remplacer les valeurs nulles par la chaîne lors de la lecture et de l’écriture du dataframe.

dateFormat

Format de date valide

DATE_FORMAT

Permet de définir une chaîne indiquant un format de date. Le format par défaut est yyyy-MM-dd.

timestampFormat

Format d’horodatage valide

TIMESTAMP_FORMAT

Permet de définir une chaîne indiquant un format d’horodatage. Le format par défaut est yyyy-MM-dd “T’HH: mm:ss.

escape

Tout caractère unique

ESCAPE

Permet de définir un caractère unique comme caractère d’échappement afin de remplacer le caractère d’échappement par défaut (\).

inferSchema

Vrai ou faux

INFER_SCHEMA

Détecte automatiquement le schéma de fichier

mergeSchema

Vrai ou faux

N/A

Pas nécessaire dans Snowflake, car cela se produit chaque fois que infer_schema détermine la structure du fichier parquet

  • Pour l’option modifiedBefore / modifiedAfter, vous pouvez obtenir le même résultat dans Snowflake en utilisant les colonnes de métadonnées et en ajoutant un filtre comme : df.filter(METADATA_FILE_LAST_MODIFIED > 'some_date').

  • Pour plus d’assistance, vous pouvez nous envoyer un e-mail à sma-support@snowflake.com ou signaler un problème dans l’outil SMA.

SPRKPY1044

Avertissement

Ce code de problème est obsolète depuis Spark Conversion Core Version 2.4.0

Message : pyspark.sql.functions.split a une solution de contournement

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.functions.split qui dispose d’une solution de contournement.

Scénarios

Il existe plusieurs scénarios en fonction du nombre de paramètres transmis à la méthode.

Scénario 1

Entrée

Voici un exemple où la fonction split n’a que les paramètres str et pattern

F.split('col', '\\|')
Copy

Sortie

L’outil affiche l’EWI SPRKPY1044 en indiquant qu’il existe une solution de contournement.

#EWI: SPRKPY1044 => pyspark.sql.functions.split has a workaround, see the documentation for more info
F.split('col', '\\|')
Copy

Correction recommandée

Comme solution de contournement, vous pouvez appeler la fonction snowflake.snowpark.functions.lit avec le paramètre du modèle et l’envoyer dans la scission.

F.split('col', lit('\\|'))
## the result of lit will be sent to the split function
Copy

Scénario 2

Entrée

Voici un autre exemple où la fonction split a pour paramètres str, pattern et limit.

F.split('col', '\\|', 2)
Copy

Sortie

L’outil affiche l’EWI SPRKPY1044 en indiquant qu’il existe une solution de contournement.

#EWI: SPRKPY1044 => pyspark.sql.functions.split has a workaround, see the documentation for more info
F.split('col', '\\|', 2)
Copy

Correction recommandée

Ce scénario spécifique n’est pas pris en charge.

Recommandations supplémentaires

SPRKPY1015

Message : pyspark.sql.functions.atanh a une solution de contournement

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.functions.atanh qui dispose d’une solution de contournement.

Scénario

Entrée

Dans cet exemple, pyspark calcule l’atanh pour un dataframe à l’aide de pyspark.sql.functions.atanh.

from pyspark.sql import SparkSession
from pyspark.sql.functions import atanh
spark = SparkSession.builder.getOrCreate()
data = [['V1', 0.14],
        ['V2', 0.32],
        ['V3', 0.4],
        ['V4', -0.36]]

columns = ['Paremeter', 'value']
df = spark.createDataFrame(data, columns)
df_result = df.withColumn("atanh_value", atanh(df["value"]))
Copy

Sortie

SMA renvoie l’EWI SPRKPY1015 sur la ligne où atanh est utilisé, ce qui vous permet d’identifier l’endroit à corriger.

from snowflake.snowpark import Session

spark = Session.builder.getOrCreate()
spark.update_query_tag({"origin":"sf_sit","name":"sma","version":{"major":0,"minor":0,"patch":0},"attributes":{"language":"Python"}})
data = [['V1', 0.14],
        ['V2', 0.32],
        ['V3', 0.4],
        ['V4', -0.36]]

columns = ['Paremeter', 'value']
df = spark.createDataFrame(data, columns)
#EWI: SPRKPY1015 => pyspark.sql.functions.atanh has a workaround, see documentation for more info
df_result = df.withColumn("atanh_value", atanh(df["value"]))
Copy

Correction recommandée

Il n’y a pas d’implémentation « atanh » directe, mais on peut utiliser « call_function » à la place, et utiliser « atanh » comme premier paramètre et colName comme second.

import snowflake.snowpark as snowpark
from snowflake.snowpark import Session
from snowflake.snowpark.functions import call_function, col

spark = Session.builder.getOrCreate()
spark.update_query_tag({"origin":"sf_sit","name":"sma","version":{"major":0,"minor":0,"patch":0},"attributes":{"language":"Python"}})
data = [['V1', 0.14],
        ['V2', 0.32],
        ['V3', 0.4],
        ['V4', -0.36]]

columns = ['Paremeter', 'value']
df = spark.createDataFrame(data, columns)
df_result = df.select(call_function('atanh', col('value')))
Copy

Recommandations supplémentaires

SPRKPY1005

Avertissement

Ce code de problème est obsolète depuis Spark Conversion Core Version 4.8.0

Message : pyspark.conf.SparkConf n’est pas requis

Catégoriey ** :** Avertissement.

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.conf.SparkConf.set qui n’est pas requis.

Scénario

Entrée

SparkConf peut être appelé sans paramètres ou avec loadDefaults.

from pyspark import SparkConf

my_conf = SparkConf(loadDefaults=True)
Copy

Sortie

Dans les deux cas (avec ou sans paramètres), SMA crée un objet Snowpark Session.builder :

#EWI: SPRKPY1005 => pyspark.conf.SparkConf is not required
#from pyspark import SparkConf
pass

#EWI: SPRKPY1005 => pyspark.conf.SparkConf is not required
my_conf = Session.builder.configs({"user" : "my_user", "password" : "my_password", "account" : "my_account", "role" : "my_role", "warehouse" : "my_warehouse", "database" : "my_database", "schema" : "my_schema"}).create()
Copy

Recommandations supplémentaires

  • Il s’agit de la suppression d’un paramètre inutile et de l’insertion d’un commentaire d’avertissement. L’utilisateur ne doit effectuer aucune action supplémentaire.

  • Pour plus d’assistance, vous pouvez nous envoyer un e-mail à sma-support@snowflake.com ou signaler un problème dans l’outil SMA.

SPRKPY1054

Messag : pyspark.sql.readwriter.DataFrameReader.format n’est pas pris en charge.

Catégorie : Avertissement

Description

Ce problème apparaît lorsque pyspark.sql.readwriter.DataFrameReader.format a un argument qui n’est pas pris en charge par Snowpark.

Scénarios

Il existe plusieurs scénarios en fonction du type de format que vous essayez de charger. Il peut s’agir d’un format pris en charge ou non pris en charge.

Scénario 1

Entrée

L’outil analyse le type de format que vous essayez de charger. Les formats pris en charge sont les suivants :

  • Csv

  • JSON

  • Parquet

  • Orc

L’exemple ci-dessous montre comment l’outil transforme la méthode format lorsqu’il transmet une valeur Csv.

from pyspark.sql import SparkSession
spark = SparkSession.builder.getOrCreate()

df1 = spark.read.format('csv').load('/path/to/file')
Copy

Sortie

L’outil transforme la méthode format en un appel de méthode Csv.

from snowflake.snowpark import Session
spark = Session.builder.getOrCreate()

df1 = spark.read.csv('/path/to/file')
Copy

Correction recommandée

Dans ce cas, l’outil n’affiche pas l’EWI, ce qui signifie qu’aucune correction n’est nécessaire.

Scénario 2

Entrée

L’exemple ci-dessous montre comment l’outil transforme la méthode format lorsqu’il transmet une valeur Jdbc.

from snowflake.snowpark import Session
spark = Session.builder.getOrCreate()

df2 = spark.read.format('jdbc') \
    .option("driver", "com.mysql.cj.jdbc.Driver") \
    .option("url", "jdbc:mysql://localhost:3306/emp") \
    .option("dbtable", "employee") \
    .option("user", "root") \
    .option("password", "root") \
    .load()
Copy

Sortie

L’outil affiche l’EWI SPRKPY1054 indiquant que la valeur « jdbc » n’est pas prise en charge.

from snowflake.snowpark import Session
spark = Session.builder.getOrCreate()

#EWI: SPRKPY1054 => pyspark.sql.readwriter.DataFrameReader.format with argument value "jdbc" is not supported.
#EWI: SPRKPY1002 => pyspark.sql.readwriter.DataFrameReader.load is not supported

df2 = spark.read.format('jdbc') \
    .option("driver", "com.mysql.cj.jdbc.Driver") \
    .option("url", "jdbc:mysql://localhost:3306/emp") \
    .option("dbtable", "employee") \
    .option("user", "root") \
    .option("password", "root") \
    .load()
Copy

Correction recommandée

Pour les scénarios non pris en charge, il n’y a pas de correction spécifique puisque cela dépend des fichiers qui tentent d’être lus.

Scénario 3

Entrée

L’exemple ci-dessous montre comment l’outil transforme la méthode format lorsqu’il transmet un fichier CSV, mais en utilisant une variable à la place.

from snowflake.snowpark import Session
spark = Session.builder.getOrCreate()

myFormat = 'csv'
df3 = spark.read.format(myFormat).load('/path/to/file')
Copy

Sortie

Comme l’outil ne peut pas déterminer la valeur de la variable dans l’environnement d’exécution, il affiche l’EWI SPRKPY1054 qui indique que la valeur «  » n’est pas prise en charge.

from snowflake.snowpark import Session
spark = Session.builder.getOrCreate()

myFormat = 'csv'
#EWI: SPRKPY1054 => pyspark.sql.readwriter.DataFrameReader.format with argument value "" is not supported.
#EWI: SPRKPY1002 => pyspark.sql.readwriter.DataFrameReader.load is not supported
df3 = spark.read.format(myFormat).load('/path/to/file')
Copy

Correction recommandée

Pour contourner le problème, vous pouvez vérifier la valeur de la variable et l’ajouter sous forme de chaîne à l’appel format.

Recommandations supplémentaires

SPRKPY1060

Message : Le mécanisme d’authentification est connection.json (modèle fourni).

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.conf.SparkConf.set.

Scénario

Entrée

Comme le mécanisme d’authentification est différent dans Snowpark, l’outil supprime les utilisations et crée un fichier de configuration des connexions (connection.json) à la place.

from pyspark import SparkConf

my_conf = SparkConf(loadDefaults=True)
Copy

Sortie

L’outil ajoute l’EWI SPRKPY1060 indiquant que le mécanisme d’authentification est différent.

#EWI: SPRKPY1002 => pyspark.conf.SparkConf is not supported
#EWI: SPRKPY1060 => The authentication mechanism is connection.json (template provided).
#my_conf = Session.builder.configs(connection_parameter).getOrCreate()

my_conf = None
Copy

Correction recommandée

Pour créer une connexion, il est nécessaire que vous remplissiez les informations dans le fichier connection.json.

{
  "user": "<USER>",
  "password": "<PASSWORD>",
  "account": "<ACCOUNT>",
  "role": "<ROLE>",
  "warehouse": "<WAREHOUSE>",
  "database": "<DATABASE>",
  "schema": "<SCHEMA>"
}
Copy

Recommandations supplémentaires

SPRKPY1031

Avertissement

Ce code de problème est obsolète depuis Spark Conversion Core 2.7.0

Message : pyspark.sql.column.Column.contains a une solution de contournement. Voir la documentation pour plus d’informations

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil SMA détecte une utilisation de la fonction pyspark.sql.column.Column.contains, qui dispose d’une solution de contournement.

Scénario

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de la fonction pyspark.sql.column.Column.contains qui génère cet EWI. Dans cet exemple, la fonction contains est utilisée pour filtrer les lignes dont la colonne « City » contient la sous-chaîne « New ».

df = spark.createDataFrame([("Alice", "New York"), ("Bob", "Los Angeles"), ("Charlie", "Chicago")], ["Name", "City"])
df_filtered = df.filter(col("City").contains("New"))
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1031 au code de sortie pour vous indiquer que cette fonction n’est pas directement prise en charge par Snowpark, mais qu’il existe une solution de contournement.

df = spark.createDataFrame([("Alice", "New York"), ("Bob", "Los Angeles"), ("Charlie", "Chicago")], ["Name", "City"])
#EWI: SPRKPY1031 => pyspark.sql.column.Column.contains has a workaround, see documentation for more info
df_filtered = df.filter(col("City").contains("New"))
Copy

Correction recommandée

Comme solution de contournement, vous pouvez utiliser la fonction snowflake.snowpark.functions.contains en transmettant la colonne comme premier argument et l’élément à rechercher comme second argument. Si l’élément à rechercher est une valeur littérale, il doit être converti en une expression de colonne à l’aide de la fonction lit.

from snowflake.snowpark import functions as f
df = spark.createDataFrame([("Alice", "New York"), ("Bob", "Los Angeles"), ("Charlie", "Chicago")], ["Name", "City"])
df_filtered = df.filter(f.contains(col("City"), f.lit("New")))
Copy

Recommandations supplémentaires

SPRKPY1020

Message : pyspark.sql.functions.instr a une solution de contournement

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.functions.instr qui dispose d’une solution de contournement.

Scénario

Entrée

Voici un exemple d’utilisation de pyspark instr :

from pyspark.sql import SparkSession
from pyspark.sql.functions import instr
spark = SparkSession.builder.getOrCreate()
df = spark.createDataFrame([('abcd',)], ['test',])
df.select(instr(df.test, 'cd').alias('result')).collect()
Copy

Sortie :

SMA renvoie l’EWI SPRKPY1020 sur la ligne où instr est utilisé, ce qui vous permet d’identifier l’endroit à corriger.

from snowflake.snowpark import Session

spark = Session.builder.getOrCreate()
spark.update_query_tag({"origin":"sf_sit","name":"sma","version":{"major":0,"minor":0,"patch":0},"attributes":{"language":"Python"}})
df = spark.createDataFrame([('abcd',)], ['test',])
#EWI: SPRKPY1020 => pyspark.sql.functions.instr has a workaround, see documentation for more info
df.select(instr(df.test, 'cd').alias('result')).collect()
Copy

Correction recommandée

Exige une modification manuelle en utilisant la fonction charindex et en changeant l’ordre des deux premiers paramètres.

import snowflake.snowpark as snowpark
from snowflake.snowpark import Session
from snowflake.snowpark.functions import charindex, lit

spark = Session.builder.getOrCreate()
spark.update_query_tag({"origin":"sf_sit","name":"sma","version":{"major":0,"minor":0,"patch":0},"attributes":{"language":"Python"}})
df = spark.createDataFrame([('abcd',)], ['test',])
df.select(charindex(lit('cd'), df.test).as_('result')).show()
Copy

Recommandation supplémentaire

SPRKPY1071

Message : La fonction pyspark.rdd.RDD.getNumPartitions n’est pas requise dans Snowpark. Vous devez donc supprimer toutes les références.

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de la fonction pyspark.rdd.RDD.getNumPartitions. Snowflake utilise un mécanisme de micro-partitionnement, l’utilisation de cette fonction n’est donc pas requise.

Scénario

Entrée

getNumPartitions renvoie la quantité de partitions sur un RDD.

df = spark.createDataFrame([('2015-04-08',), ('5',), [Row(a=1, b="b")]], ['dt', 'num', 'row'])

print(df.getNumPartitions())
Copy

Sortie

L’outil ajoute cet EWI pour vous indiquer que getNumPartitions n’est pas requis.

df = spark.createDataFrame([('2015-04-08',), ('5',), [Row(a=1, b="b")]], ['dt', 'num', 'row'])
#EWI: SPRKPY1071 => The getNumPartitions are not required in Snowpark. So, you should remove all references.

print(df.getNumPartitions())
Copy

Correction recommandée

Supprimez toutes les utilisations de cette fonction.

df = spark.createDataFrame([('2015-04-08',), ('5',), [Row(a=1, b="b")]], ['dt', 'num', 'row'])
Copy

Recommandations supplémentaires

SPRKPY1082

Message : La fonction pyspark.sql.readwriter.DataFrameReader.load n’est pas prise en charge. La solution consiste à utiliser la méthode Snowpark DataFrameReader.format à la place (avro csv, json, orc, parquet). Le paramètre path doit être un emplacement de zone de préparation.

Catégorie : Avertissement

Description

La fonction pyspark.sql.readwriter.DataFrameReader.load n’est pas prise en charge. La solution consiste à utiliser les méthodes Snowpark DataFrameReader à la place.

Scénarios

La signature Spark de cette méthode DataFrameReader.load(path, format, schema, **options) n’existe pas dans Snowpark. Par conséquent, toute utilisation de la fonction de chargement aura pour conséquence un EWI dans le code de sortie.

Scénario 1

Entrée

Vous trouverez ci-dessous un exemple qui tente de charger des données depuis une source CSV.

path_csv_file = "/path/to/file.csv"

schemaParam = StructType([
        StructField("Name", StringType(), True),
        StructField("Superhero", StringType(), True)
    ])

my_session.read.load(path_csv_file, "csv").show()
my_session.read.load(path_csv_file, "csv", schema=schemaParam).show()
my_session.read.load(path_csv_file, "csv", schema=schemaParam, lineSep="\r\n", dateFormat="YYYY/MM/DD").show()
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1082 pour vous indiquer que cette fonction n’est pas prise en charge par Snowpark, mais qu’il existe une solution de contournement.

path_csv_file = "/path/to/file.csv"

schemaParam = StructType([
        StructField("Name", StringType(), True),
        StructField("Superhero", StringType(), True)
    ])
#EWI: SPRKPY1082 => The pyspark.sql.readwriter.DataFrameReader.load function is not supported. A workaround is to use Snowpark DataFrameReader format specific method instead (avro csv, json, orc, parquet). The path parameter should be a stage location.

my_session.read.load(path_csv_file, "csv").show()
#EWI: SPRKPY1082 => The pyspark.sql.readwriter.DataFrameReader.load function is not supported. A workaround is to use Snowpark DataFrameReader format specific method instead (avro csv, json, orc, parquet). The path parameter should be a stage location.
my_session.read.load(path_csv_file, "csv", schema=schemaParam).show()
#EWI: The pyspark.sql.readwriter.DataFrameReader.load function is not supported. A workaround is to use Snowpark DataFrameReader format specific method instead (avro csv, json, orc, parquet). The path parameter should be a stage location.
my_session.read.load(path_csv_file, "csv", schema=schemaParam, lineSep="\r\n", dateFormat="YYYY/MM/DD").show()
Copy

Correction recommandée

Pour contourner le problème, vous pouvez utiliser les méthodes Snowpark DataFrameReader à la place.

  • Correction des paramètres path et format :

    • Remplacez la méthode load par la méthode csv.

    • Le premier paramètre path doit être dans une zone de préparation pour présenter une équivalence avec Snowpark.

Vous trouverez ci-dessous un exemple qui crée une zone de préparation temporelle et y place le fichier, puis appelle la méthode CSV.

path_csv_file = "/path/to/file.csv"

## Stage creation

temp_stage = f'{Session.get_fully_qualified_current_schema()}.{_generate_prefix("TEMP_STAGE")}'
my_session.sql(f'CREATE TEMPORARY STAGE IF NOT EXISTS {temp_stage}').show()
my_session.file.put(f"file:///path/to/file.csv", f"@{temp_stage}")
stage_file_path = f"{temp_stage}file.csv"

schemaParam = StructType([
        StructField("Name", StringType(), True),
        StructField("Superhero", StringType(), True)
    ])

my_session.read.csv(stage_file_path).show()
Copy
  • Correction du paramètre schema :

    • Le schéma peut être défini en utilisant la fonction schema comme suit :

schemaParam = StructType([
        StructField("name", StringType(), True),
        StructField("city", StringType(), True)
    ])

df = my_session.read.schema(schemaParam).csv(temp_stage)
Copy
  • Correction du paramètre options :

Les options entre Spark et Snowpark ne sont pas les mêmes. Dans ce cas, lineSep et dateFormat sont remplacés par RECORD_DELIMITER et DATE_FORMAT, la section Recommandations supplémentaires contient une table avec toutes les équivalences.

Vous trouverez ci-dessous un exemple qui crée un dictionnaire avec RECORD_DELIMITER et DATE_FORMAT, et qui appelle la méthode options avec ce dictionnaire.

optionsParam = {"RECORD_DELIMITER": "\r\n", "DATE_FORMAT": "YYYY/MM/DD"}
df = my_session.read.options(optionsParam).csv(stage)
Copy

Scénario 2

Entrée

Vous trouverez ci-dessous un exemple qui tente de charger des données depuis une source JSON.

path_json_file = "/path/to/file.json"

schemaParam = StructType([
        StructField("Name", StringType(), True),
        StructField("Superhero", StringType(), True)
    ])

my_session.read.load(path_json_file, "json").show()
my_session.read.load(path_json_file, "json", schema=schemaParam).show()
my_session.read.load(path_json_file, "json", schema=schemaParam, dateFormat="YYYY/MM/DD", timestampFormat="YYYY-MM-DD HH24:MI:SS.FF3").show()
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1082 pour vous indiquer que cette fonction n’est pas prise en charge par Snowpark, mais qu’il existe une solution de contournement.

path_json_file = "/path/to/file.json"

schemaParam = StructType([
        StructField("Name", StringType(), True),
        StructField("Superhero", StringType(), True)
    ])
#EWI: SPRKPY1082 => The pyspark.sql.readwriter.DataFrameReader.load function is not supported. A workaround is to use Snowpark DataFrameReader format specific method instead (avro csv, json, orc, parquet). The path parameter should be a stage location.

my_session.read.load(path_json_file, "json").show()
#EWI: SPRKPY1082 => The pyspark.sql.readwriter.DataFrameReader.load function is not supported. A workaround is to use Snowpark DataFrameReader format specific method instead (avro csv, json, orc, parquet). The path parameter should be a stage location.
my_session.read.load(path_json_file, "json", schema=schemaParam).show()
#EWI: SPRKPY1082 => The pyspark.sql.readwriter.DataFrameReader.load function is not supported. A workaround is to use Snowpark DataFrameReader format specific method instead (avro csv, json, orc, parquet). The path parameter should be a stage location.
my_session.read.load(path_json_file, "json", schema=schemaParam, dateFormat="YYYY/MM/DD", timestampFormat="YYYY-MM-DD HH24:MI:SS.FF3").show()
Copy

Correction recommandée

Pour contourner le problème, vous pouvez utiliser les méthodes Snowpark DataFrameReader à la place.

  • Correction des paramètres path et format :

    • Remplacez la méthode load par la méthode json.

    • Le premier paramètre path doit être dans une zone de préparation pour présenter une équivalence avec Snowpark.

Vous trouverez ci-dessous un exemple qui crée une zone de préparation temporelle et y place le fichier, puis appelle la méthode JSON.

path_json_file = "/path/to/file.json"

## Stage creation

temp_stage = f'{Session.get_fully_qualified_current_schema()}.{_generate_prefix("TEMP_STAGE")}'
my_session.sql(f'CREATE TEMPORARY STAGE IF NOT EXISTS {temp_stage}').show()
my_session.file.put(f"file:///path/to/file.json", f"@{temp_stage}")
stage_file_path = f"{temp_stage}file.json"

schemaParam = StructType([
        StructField("Name", StringType(), True),
        StructField("Superhero", StringType(), True)
    ])

my_session.read.json(stage_file_path).show()
Copy
  • Correction du paramètre schema :

    • Le schéma peut être défini en utilisant la fonction schema comme suit :

schemaParam = StructType([
        StructField("name", StringType(), True),
        StructField("city", StringType(), True)
    ])

df = my_session.read.schema(schemaParam).json(temp_stage)
Copy
  • Correction du paramètre options :

Les options entre Spark et Snowpark ne sont pas les mêmes. Dans ce cas, dateFormat et timestampFormat sont remplacés par DATE_FORMAT et TIMESTAMP_FORMAT, la section Recommandations supplémentaires contient une table avec toutes les équivalences.

Vous trouverez ci-dessous un exemple qui crée un dictionnaire avec DATE_FORMAT et TIMESTAMP_FORMAT, et qui appelle la méthode options avec ce dictionnaire.

optionsParam = {"DATE_FORMAT": "YYYY/MM/DD", "TIMESTAMP_FORMAT": "YYYY-MM-DD HH24:MI:SS.FF3"}
df = Session.read.options(optionsParam).json(stage)
Copy

Scénario 3

Entrée

Vous trouverez ci-dessous un exemple qui tente de charger des données depuis une source PARQUET.

path_parquet_file = "/path/to/file.parquet"

schemaParam = StructType([
        StructField("Name", StringType(), True),
        StructField("Superhero", StringType(), True)
    ])

my_session.read.load(path_parquet_file, "parquet").show()
my_session.read.load(path_parquet_file, "parquet", schema=schemaParam).show()
my_session.read.load(path_parquet_file, "parquet", schema=schemaParam, pathGlobFilter="*.parquet").show()
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1082 pour vous indiquer que cette fonction n’est pas prise en charge par Snowpark, mais qu’il existe une solution de contournement.

path_parquet_file = "/path/to/file.parquet"

schemaParam = StructType([
        StructField("Name", StringType(), True),
        StructField("Superhero", StringType(), True)
    ])
#EWI: SPRKPY1082 => The pyspark.sql.readwriter.DataFrameReader.load function is not supported. A workaround is to use Snowpark DataFrameReader format specific method instead (avro csv, json, orc, parquet). The path parameter should be a stage location.

my_session.read.load(path_parquet_file, "parquet").show()
#EWI: SPRKPY1082 => The pyspark.sql.readwriter.DataFrameReader.load function is not supported. A workaround is to use Snowpark DataFrameReader format specific method instead (avro csv, json, orc, parquet). The path parameter should be a stage location.
my_session.read.load(path_parquet_file, "parquet", schema=schemaParam).show()
#EWI: SPRKPY1082 => The pyspark.sql.readwriter.DataFrameReader.load function is not supported. A workaround is to use Snowpark DataFrameReader format specific method instead (avro csv, json, orc, parquet). The path parameter should be a stage location.
my_session.read.load(path_parquet_file, "parquet", schema=schemaParam, pathGlobFilter="*.parquet").show()
Copy

Correction recommandée

Pour contourner le problème, vous pouvez utiliser les méthodes Snowpark DataFrameReader à la place.

  • Correction des paramètres path et format :

    • Remplacez la méthode load par la méthode parquet.

    • Le premier paramètre path doit être dans une zone de préparation pour présenter une équivalence avec Snowpark.

Vous trouverez ci-dessous un exemple qui crée une zone de préparation temporelle et y place le fichier, puis appelle la méthode PARQUET.

path_parquet_file = "/path/to/file.parquet"

## Stage creation

temp_stage = f'{Session.get_fully_qualified_current_schema()}.{_generate_prefix("TEMP_STAGE")}'
my_session.sql(f'CREATE TEMPORARY STAGE IF NOT EXISTS {temp_stage}').show()
my_session.file.put(f"file:///path/to/file.parquet", f"@{temp_stage}")
stage_file_path = f"{temp_stage}file.parquet"

schemaParam = StructType([
        StructField("Name", StringType(), True),
        StructField("Superhero", StringType(), True)
    ])

my_session.read.parquet(stage_file_path).show()
Copy
  • Correction du paramètre schema :

    • Le schéma peut être défini en utilisant la fonction schema comme suit :

schemaParam = StructType([
        StructField("name", StringType(), True),
        StructField("city", StringType(), True)
    ])

df = my_session.read.schema(schemaParam).parquet(temp_stage)
Copy
  • Correction du paramètre options :

Les options entre Spark et Snowpark ne sont pas les mêmes. Dans ce cas, pathGlobFilter est remplacé par PATTERN, la section Recommandations supplémentaires contient une table avec toutes les équivalences.

Vous trouverez ci-dessous un exemple qui crée un dictionnaire avec PATTERN, et qui appelle la méthode options avec ce dictionnaire.

optionsParam = {"PATTERN": "*.parquet"}
df = Session.read.options(optionsParam).parquet(stage)
Copy

Recommandations supplémentaires

  • Tenez compte du fait que les options entre Spark et Snowpark ne sont pas les mêmes, mais qu’elles peuvent être mappées :

Options Spark

Valeur possible

Équivalent Snowpark

Description

header

Vrai ou faux

SKIP_HEADER = 1 / SKIP_HEADER = 0

Pour utiliser la première ligne d’un fichier comme nom de colonne.

delimiter

Tout séparateur de champ à un ou plusieurs caractères

FIELD_DELIMITER

Pour spécifier un ou plusieurs caractères comme séparateur pour chaque colonne/champ.

sep

Tout séparateur de champ à un caractère

FIELD_DELIMITER

Pour spécifier un seul caractère comme séparateur pour chaque colonne/champ.

encoding

UTF-8, UTF-16, etc…

ENCODING

Pour décoder les fichiers CSV selon le type d’encodage donné. L’encodage par défaut est UTF-8

ligneSep

Tout séparateur de lignes à un caractère

RECORD_DELIMITER

Pour définir le séparateur de lignes à utiliser pour l’analyse du fichier.

pathGlobFilter

Modèle de fichier

PATTERN

Pour définir un modèle permettant de lire uniquement les fichiers dont les noms correspondent au modèle.

recursiveFileLookup

Vrai ou faux

N/A

Pour analyser de manière récursive un répertoire afin d’y lire des fichiers. La valeur par défaut de cette option est False.

quote

Caractère unique à mettre entre guillemets

FIELD_OPTIONALLY_ENCLOSED_BY

Permet de mettre entre guillemets les champs/colonnes contenant des champs où le délimiteur/séparateur peut faire partie de la valeur. Ce caractère permet de mettre entre guillemets tous les champs lorsqu’il est utilisé avec l’option quoteAll. La valeur par défaut de cette option est guillemet double (« ).

nullValue

Chaîne pour remplacer la valeur nulle

NULL_IF

Permet de remplacer les valeurs nulles par la chaîne lors de la lecture et de l’écriture du dataframe.

dateFormat

Format de date valide

DATE_FORMAT

Permet de définir une chaîne indiquant un format de date. Le format par défaut est yyyy-MM-dd.

timestampFormat

Format d’horodatage valide

TIMESTAMP_FORMAT

Permet de définir une chaîne indiquant un format d’horodatage. Le format par défaut est yyyy-MM-dd “T’HH: mm:ss.

escape

Tout caractère unique

ESCAPE

Permet de définir un caractère unique comme caractère d’échappement afin de remplacer le caractère d’échappement par défaut (\).

inferSchema

Vrai ou faux

INFER_SCHEMA

Détecte automatiquement le schéma de fichier

mergeSchema

Vrai ou faux

N/A

Pas nécessaire dans Snowflake, car cela se produit chaque fois que infer_schema détermine la structure du fichier parquet

  • Pour l’option modifiedBefore / modifiedAfter, vous pouvez obtenir le même résultat dans Snowflake en utilisant les colonnes de métadonnées et en ajoutant un filtre comme : df.filter(METADATA_FILE_LAST_MODIFIED > 'some_date').

  • Pour plus d’assistance, vous pouvez nous envoyer un e-mail à sma-support@snowflake.com ou signaler un problème dans l’outil SMA.

SPRKPY1045

Message : pyspark.sql.functions.map_values a une solution de contournement

Catégorie : Avertissement

Description

Cette fonction est utilisée pour extraire la liste des valeurs d’une colonne qui contient une carte/un dictionnaire (clés/valeurs).

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.functions.map_values qui dispose d’une solution de contournement.

Scénario

Entrée

Voici un exemple de l’utilisation de la méthode map_values.

df = spark.createDataFrame(
    [(1, {'Apple': 'Fruit', 'Potato': 'Vegetable'})],
    ("id", "a_map"))

df.select(map_values("a_map")).show()
Copy

Sortie

L’outil ajoute l’EWI SPRKPY1045 indiquant qu’une solution de contournement peut être mise en œuvre.

df = spark.createDataFrame(
    [(1, {'Apple': 'Fruit', 'Potato': 'Vegetable'})],
    ("id", "a_map"))
#EWI: SPRKPY1045 => pyspark.sql.functions.map_values has a workaround, see documentation for more info

df.select(map_values("a_map")).show()
Copy

Correction recommandée

En guise de solution de contournement, vous pouvez créer un udf pour obtenir les valeurs d’une colonne. L’exemple ci-dessous illustre comment créer l’udf, l’affecter à F.map_values, puis l’utiliser.

from snowflake.snowpark import functions as F
from snowflake.snowpark.types import ArrayType, MapType

map_values_udf=None

def map_values(map):
    global map_values_udf
    if not map_values_udf:
        def _map_values(map: dict)->list:
            return list(map.values())
        map_values_udf = F.udf(_map_values,return_type=ArrayType(),input_types=[MapType()],name="map_values",is_permanent=False,replace=True)
    return map_values_udf(map)

F.map_values = map_values

df.select(map_values(colDict))
Copy

Recommandations supplémentaires

SPRKPY1014

Message : pyspark.sql.functions.asinh a une solution de contournement

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.functions.asinh qui dispose d’une solution de contournement.

Scénario

Entrée

Dans cet exemple, pyspark calcule l’asinh pour un dataframe à l’aide de pyspark.sql.functions.asinh.

from pyspark.sql import SparkSession
from pyspark.sql.functions import asinh
spark = SparkSession.builder.getOrCreate()
data = [['V1', 3.0],
        ['V2', 60.0],
        ['V3', 14.0],
        ['V4', 3.1]]

columns = ['Paremeter', 'value']
df = spark.createDataFrame(data, columns)
df_result = df.withColumn("asinh_value", asinh(df["value"]))
Copy

Sortie

SMA renvoie l’EWI SPRKPY1014 sur la ligne où asinh est utilisé, ce qui vous permet d’identifier l’endroit à corriger.

from snowflake.snowpark import Session

spark = Session.builder.getOrCreate()
spark.update_query_tag({"origin":"sf_sit","name":"sma","version":{"major":0,"minor":0,"patch":0},"attributes":{"language":"Python"}})
data = [['V1', 3.0],
        ['V2', 60.0],
        ['V3', 14.0],
        ['V4', 3.1]]

columns = ['Paremeter', 'value']
df = spark.createDataFrame(data, columns)
#EWI: SPRKPY1014 => pyspark.sql.functions.asinh has a workaround, see documentation for more info
df_result = df.withColumn("asinh_value", asinh(df["value"]))
Copy

Correction recommandée

Il n’y a pas d’implémentation « asinh » directe, mais on peut utiliser « call_function » à la place, et utiliser « asinh » comme premier paramètre et colName comme second.

import snowflake.snowpark as snowpark
from snowflake.snowpark import Session
from snowflake.snowpark.functions import call_function, col

spark = Session.builder.getOrCreate()
spark.update_query_tag({"origin":"sf_sit","name":"sma","version":{"major":0,"minor":0,"patch":0},"attributes":{"language":"Python"}})
data = [['V1', 3.0],
        ['V2', 60.0],
        ['V3', 14.0],
        ['V4', 3.1]]

columns = ['Paremeter', 'value']
df = spark.createDataFrame(data, columns)
df_result = df.select(call_function('asinh', col('value')))
Copy

Recommandations supplémentaires

SPRKPY1004

Message&#x65 ; ** :** La table des symboles n’a pas pu être chargée.

Catégorie&#x79 ; ** :** Erreur d’analyse.

Description

Ce problème apparaît en cas d’erreur inattendue dans le processus d’exécution de l’outil. La table des symboles ne pouvant être chargée, l’outil ne peut pas lancer le processus d’évaluation ou de conversion.

Recommandations supplémentaires

SPRKPY1055

Message : La valeur de clé pyspark.sql.readwriter.DataFrameReader.option n’est pas prise en charge.

Catégorie : Avertissement

Description

Ce problème apparaît lorsque la valeur de clé pyspark.sql.readwriter.DataFrameReader.option n’est pas prise en charge par SnowFlake.

L’outil analyse les paramètres de l’appel de l’option et, en fonction de la méthode (CSV ou JSON ou PARQUET), la valeur clé peut avoir ou non un équivalent dans Snowpark. Si tous les paramètres ont un équivalent, l’outil n’ajoute pas l’EWI et remplace la valeur clé par son équivalent. Dans le cas contraire, l’outil ajoute l’EWI.

Liste des équivalences :

  • Équivalences pour CSV :

Clés d’option Spark

Equivalences Snowpark

sep

FIELD_DELIMITER

header

PARSE_HEADER

ligneSep

RECORD_DELIMITER

pathGlobFilter

PATTERN

quote

FIELD_OPTIONALLY_ENCLOSED_BY

nullValue

NULL_IF

dateFormat

DATE_FORMAT

timestampFormat

TIMESTAMP_FORMAT

inferSchema

INFER_SCHEMA

delimiter

FIELD_DELIMITER

  • Équivalences pour JSON :

Clés d’option Spark

Equivalences Snowpark

dateFormat

DATE_FORMAT

timestampFormat

TIMESTAMP_FORMAT

pathGlobFilter

PATTERN

  • Équivalences pour PARQUET :

Clés d’option Spark

Equivalences Snowpark

pathGlobFilter

PATTERN

Toute autre option clé qui ne figure pas dans l’une des tables ci-dessus, n’est pas prise en charge ou n’a pas d’équivalent dans Snowpark. Si c’est le cas, l’outil ajoute l’EWI avec les informations sur les paramètres et le retire de la chaîne.

Scénarios

Les scénarios suivants s’appliquent à CSV, JSON et PARQUET.

Il existe plusieurs scénarios en fonction de la valeur de la clé utilisée dans la méthode option.

Scénario 1

Entrée

Vous trouverez ci-dessous un exemple d’appel option à l’aide d’une clé équivalente.

from pyspark.sql import SparkSession

spark = SparkSession.builder.getOrCreate()

## CSV example:
spark.read.option("header", True).csv(csv_file_path)

## Json example:
spark.read.option("dateFormat", "dd-MM-yyyy").json(json_file_path)

## Parquet example:
spark.read.option("pathGlobFilter", "*.parquet").parquet(parquet_file_path)
Copy

Sortie

L’outil transforme la clé avec l’équivalent correct.

from snowflake.snowpark import Session

spark = Session.builder.getOrCreate()

## CSV example:
spark.read.option("PARSE_HEADER", True).csv(csv_file_path)

## Json example:
spark.read.option("DATE_FORMAT", "dd-MM-yyyy").json(json_file_path)

## Parquet example:
spark.read.option("PATTERN", "*.parquet").parquet(parquet_file_path)
Copy

Correction recommandée

Étant donné que l’outil transforme la valeur de la clé, aucune correction n’est nécessaire.

Scénario 2

Entrée

Vous trouverez ci-dessous un exemple d’appel option à l’aide d’une clé non équivalente.

from pyspark.sql import SparkSession

spark = SparkSession.builder.getOrCreate()

## CSV example:
spark.read.option("anotherKeyValue", "myVal").csv(csv_file_path)

## Json example:
spark.read.option("anotherKeyValue", "myVal").json(json_file_path)

## Parquet example:
spark.read.option("anotherKeyValue", "myVal").parquet(parquet_file_path)
Copy

Sortie

L’outil ajoute l’EWI SPRKPY1055 indiquant que la clé n’est pas prise en charge et retire l’appel option.

from snowflake.snowpark import Session

spark = Session.builder.getOrCreate()

## CSV example:
#EWI: SPRKPY1055 => pyspark.sql.readwriter.DataFrameReader.option with key value "anotherKeyValue" is not supported.
spark.read.csv(csv_file_path)

## Json example:
#EWI: SPRKPY1055 => pyspark.sql.readwriter.DataFrameReader.option with key value "anotherKeyValue" is not supported.
spark.read.json(json_file_path)

## Parquet example:
#EWI: SPRKPY1055 => pyspark.sql.readwriter.DataFrameReader.option with key value "anotherKeyValue" is not supported.
spark.read.parquet(parquet_file_path)
Copy

Correction recommandée

Il est recommandé de vérifier le comportement après la transformation.

Recommandations supplémentaires

  • En présence de paramètres non équivalents, il est recommandé de vérifier le comportement après la transformation.

  • Pour plus d’assistance, vous pouvez nous envoyer un e-mail à sma-support@snowflake.com ou signaler un problème dans l’outil SMA.

SPRKPY1061

Message : Snowpark ne prend en charge les fonctions unix_timestamp

Catégorie : Avertissement

Description

Dans Snowpark, le premier paramètre est obligatoire ; le problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.functions.unix_timestamp sans paramètre.

Scénario

Entrée

Vous trouverez ci-dessous un exemple qui illustre l’appel de la méthode unix_timestamp sans paramètres.

data = [["2015-04-08", "10"],["2015-04-10", "15"]]

df = spark.createDataFrame(data, ['dt', 'val'])
df.select(unix_timestamp()).show()
Copy

Sortie

La signature Snowpark pour cette fonction unix_timestamp(e: ColumnOrName, fmt: Optional["Column"] = None). Comme vous pouvez le remarquer, le premier paramètre est requis.

L’outil ajoute cet EWI SPRKPY1061 pour vous informer que la fonction unix_timestamp sans paramètre n’est pas prise en charge par Snowpark.

data = [["2015-04-08", "10"],["2015-04-10", "15"]]

df = spark.createDataFrame(data, ['dt', 'val'])
#EWI: SPRKPY1061 => Snowpark does not support unix_timestamp functions with no parameters. See documentation for more info.
df.select(unix_timestamp()).show()
Copy

Correction recommandée

En guise de solution de contournement, vous pouvez ajouter au moins le nom ou la colonne de la chaîne d’horodatage.

data = [["2015-04-08", "10"],["2015-04-10", "15"]]

df = spark.createDataFrame(data, ["dt", "val"])
df.select(unix_timestamp("dt")).show()
Copy

Recommandations supplémentaires

SPRKPY1030

Avertissement

Ce code de problème est maintenant obsolète.

Message : pyspark.sql.session.SparkSession.Builder.appName a une solution de contournement. Voir la documentation pour plus d’informations.

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil SMA détecte une utilisation de la fonction pyspark.sql.session.SparkSession.Builder.appName, qui dispose d’une solution de contournement.

Scénario

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de la fonction pyspark.sql.session.SparkSession.Builder.appName qui génère cet EWI. Dans cet exemple, la fonction appName est utilisée pour définir MyApp comme nom de l’application.

session = SparkSession.builder.appName("MyApp").getOrCreate()
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1030 au code de sortie pour vous indiquer que cette fonction n’est pas directement prise en charge par Snowpark, mais qu’il existe une solution de contournement.

#EWI: SPRKPY1030 => pyspark.sql.session.SparkSession.Builder.appName has a workaround, see documentation for more info
session = Session.builder.appName("MyApp").getOrCreate()
Copy

Correction recommandée

Pour contourner le problème, vous pouvez importer le paquet snowpark_extensions qui fournit une extension pour la fonction appName.

import snowpark_extensions
session = SessionBuilder.appName("MyApp").getOrCreate()
Copy

Recommandations supplémentaires

SPRKPY1010

Message : pyspark.sql.dataframe.DataFrame.checkpoint a une solution de contournement

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.dataframe.DataFrame.checkpoint qui dispose d’une solution de contournement.

Scénario

Entrée

Dans PySpark, les points de contrôle sont utilisés pour tronquer le plan logique d’un dataframe, ceci afin d’éviter le développement d’un plan logique.

import tempfile
from pyspark.sql import SparkSession
spark = SparkSession.builder.getOrCreate()
data = [['Q1', 300000],
        ['Q2', 60000],
        ['Q3', 500002],
        ['Q4', 130000]]

columns = ['Quarter', 'Score']
df = spark.createDataFrame(data, columns)
with tempfile.TemporaryDirectory() as d:
    spark.sparkContext.setCheckpointDir("/tmp/bb")
    df.checkpoint(False)
Copy

Sortie

SMA renvoie l’EWI SPRKPY1010 sur la ligne où approxQuantile est utilisé, ce qui vous permet d’identifier l’endroit à corriger. Notez que cela marque également le setCheckpointDir comme non pris en charge, mais un répertoire de points de contrôle n’est pas nécessaire pour la correction.

import tempfile
from snowflake.snowpark import Session
spark = Session.builder.getOrCreate()
spark.update_query_tag({"origin":"sf_sit","name":"sma","version":{"major":0,"minor":0,"patch":0},"attributes":{"language":"Python"}})
data = [['Q1', 300000],
        ['Q2', 60000],
        ['Q3', 500002],
        ['Q4', 130000]]

columns = ['Quarter', 'Score']
df = spark.createDataFrame(data, columns)
with tempfile.TemporaryDirectory() as d:
    #EWI: SPRKPY1002 => pyspark.context.SparkContext.setCheckpointDir is not supported
    spark.setCheckpointDir("/tmp/bb")
    #EWI: SPRKPY1010 => pyspark.sql.dataframe.DataFrame.checkpoint has a workaround, see documentation for more info
    df.checkpoint(False)
Copy

Correction recommandée

Snowpark élimine le besoin de points de contrôle explicites : en effet, Snowpark travaille avec des opérations basées sur SQL qui sont optimisées par le moteur d’optimisation des requêtes de Snowflake, ce qui élimine le besoin de calculs non requis ou de plans logiques qui deviennent incontrôlables.

Cependant, dans certains cas, vous pourriez avoir besoin de conserver le résultat d’un calcul d’un dataframe. Dans ce cas, vous pouvez enregistrer les résultats en écrivant le dataframe dans une table Snowflake ou dans une table temporaire Snowflake.

  • L’utilisation d’une table permanente ou le résultat du calcul est accessible à tout moment, même après la fin de la session.

from snowflake.snowpark import Session
spark = Session.builder.getOrCreate()
spark.update_query_tag({"origin":"sf_sit","name":"sma","version":{"major":0,"minor":0,"patch":0},"attributes":{"language":"Python"}})
data = [['Q1', 300000],
        ['Q2', 60000],
        ['Q3', 500002],
        ['Q4', 130000]]

columns = ['Quarter', 'Score']
df = spark.createDataFrame(data, columns)
df.write.save_as_table("my_table", table_type="temporary") # Save the dataframe into Snowflake table "my_table".
df2 = Session.table("my_table") # Now I can access the stored result quering the table "my_table"
Copy
  • Une correction alternative, l’utilisation d’une table temporaire, présente l’avantage que la table est supprimée après la fin de la session :

from snowflake.snowpark import Session
spark = Session.builder.getOrCreate()
spark.update_query_tag({"origin":"sf_sit","name":"sma","version":{"major":0,"minor":0,"patch":0},"attributes":{"language":"Python"}})
data = [['Q1', 300000],
        ['Q2', 60000],
        ['Q3', 500002],
        ['Q4', 130000]]

columns = ['Quarter', 'Score']
df = spark.createDataFrame(data, columns)
df.write.save_as_table("my_temp_table", table_type="temporary") # Save the dataframe into Snowflake table "my_temp_table".
df2 = Session.table("my_temp_table") # Now I can access the stored result quering the table "my_temp_table"
Copy

Recommandations supplémentaires

SPRKPY1101

Catégorie

Erreur d’analyse.

Description

Lorsque l’outil détecte une erreur d’analyse, il tente d’y remédier et poursuit le processus à la ligne suivante. Dans ces cas-là, il affiche l’erreur et des commentaires sur la ligne.

Cet exemple montre comment est traitée une erreur de concordance entre les espaces et les tabulations.

Code d’entrée

def foo():
    x = 5 # Spaces
	y = 6 # Tab

def foo2():
    x=6
    y=7
Copy

Code de sortie

def foo():
    x = 5 # Spaces
## EWI: SPRKPY1101 => Unrecognized or invalid CODE STATEMENT @(3, 2). Last valid token was '5' @(2, 9), failed token 'y' @(3, 2)
## y = 6 # Tab

def foo2():
    x=6
    y=7
Copy

Recommandations

  • Essayez de corriger la ligne commentée.

  • Pour plus d’assistance, envoyez-nous un e-mail à l’adresse suivante : sma-support@snowflake.com. Si vous avez un contrat de support avec Snowflake, contactez votre ingénieur commercial, qui pourra répondre à vos besoins en matière d’assistance.

SPRKPY1041

Avertissement

Ce code de problème est obsolète depuis Spark Conversion Core Version 2.9.0

Message : pyspark.sql.functions.explode_outer a une solution de contournement

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.functions.explode_outer qui dispose d’une solution de contournement.

Scénario

Entrée

L’exemple montre l’utilisation de la méthode explode_outer dans un appel sélectif.

df = spark.createDataFrame(
    [(1, ["foo", "bar"], {"x": 1.0}),
     (2, [], {}),
     (3, None, None)],
    ("id", "an_array", "a_map")
)

df.select("id", "an_array", explode_outer("a_map")).show()
Copy

Sortie

L’outil ajoute l’EWI SPRKPY1041 indiquant qu’une solution de contournement peut être mise en œuvre.

df = spark.createDataFrame(
    [(1, ["foo", "bar"], {"x": 1.0}),
     (2, [], {}),
     (3, None, None)],
    ("id", "an_array", "a_map")
)

#EWI: SPRKPY1041 => pyspark.sql.functions.explode_outer has a workaround, see documentation for more info
df.select("id", "an_array", explode_outer("a_map")).show()
Copy

Correction recommandée

Pour contourner le problème, vous pouvez importer le paquet snowpark_extensions qui contient un assistant pour la fonction explode_outer.

import snowpark_extensions

df = spark.createDataFrame(
    [(1, ["foo", "bar"], {"x": 1.0}),
     (2, [], {}),
     (3, None, None)],
    ("id", "an_array", "a_map")
)

df.select("id", "an_array", explode_outer("a_map")).show()
Copy

Recommandations supplémentaires

SPRKPY1075

Catégorie

Avertissement.

Description

La fonction parse_json n’applique pas de validation de schéma. Si vous avez besoin de filtrer/valider sur la base du schéma, vous devrez peut-être introduire une certaine logique.

Exemple

Entrée

df.select(from_json(df.value, Schema))
df.select(from_json(schema=Schema, col=df.value))
df.select(from_json(df.value, Schema, option))
Copy

Sortie

#EWI: SPRKPY1075 => The parse_json does not apply schema validation, if you need to filter/validate based on schema you might need to introduce some logic.
df.select(parse_json(df.value))
#EWI: SPRKPY1075 => The parse_json does not apply schema validation, if you need to filter/validate based on schema you might need to introduce some logic.
df.select(parse_json(df.value))
#EWI: SPRKPY1075 => The parse_json does not apply schema validation, if you need to filter/validate based on schema you might need to introduce some logic.
df.select(parse_json(df.value))
Copy

Pour la fonction from_json, le schéma n’est pas vraiment transmis pour l’inférence, il est utilisé pour la validation. Voir ces exemples :

data = [
    ('{"name": "John", "age": 30, "city": "New York"}',),
    ('{"name": "Jane", "age": "25", "city": "San Francisco"}',)
]

df = spark.createDataFrame(data, ["json_str"])
Copy

Exemple 1 : Appliquer les types de données et modifier les noms des colonnes :

## Parse JSON column with schema
parsed_df = df.withColumn("parsed_json", from_json(col("json_str"), schema))

parsed_df.show(truncate=False)

## +------------------------------------------------------+---------------------------+
## |json_str                                              |parsed_json                |
## +------------------------------------------------------+---------------------------+
## |{"name": "John", "age": 30, "city": "New York"}       |{John, 30, New York}       |
## |{"name": "Jane", "age": "25", "city": "San Francisco"}|{Jane, null, San Francisco}|
## +------------------------------------------------------+---------------------------+
## notice that values outside of the schema were dropped and columns not matched are returned as null
Copy

Exemple 2 : Sélectionner des colonnes spécifiques :

## Define a schema with only the columns we want to use
partial_schema = StructType([
    StructField("name", StringType(), True),
    StructField("city", StringType(), True)
])

## Parse JSON column with partial schema
partial_df = df.withColumn("parsed_json", from_json(col("json_str"), partial_schema))

partial_df.show(truncate=False)

## +------------------------------------------------------+---------------------+
## |json_str                                              |parsed_json          |
## +------------------------------------------------------+---------------------+
## |{"name": "John", "age": 30, "city": "New York"}       |{John, New York}     |
## |{"name": "Jane", "age": "25", "city": "San Francisco"}|{Jane, San Francisco}|
## +------------------------------------------------------+---------------------+
## there is also an automatic filtering
Copy

Recommandations

  • Pour plus d’assistance, vous pouvez nous envoyer un e-mail à l’adresse suivante : sma-support@snowflake.com. Si vous avez un contrat de support avec Snowflake, contactez votre ingénieur commercial, qui pourra répondre à vos besoins en matière d’assistance.

  • Outils utiles PEP-8 et Ré-indenter.

SPRKPY1024

Message : pyspark.sql.functions.log2 a une solution de contournement. Voir la documentation pour plus d’informations

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil SMA détecte une utilisation de la fonction pyspark.sql.functions.log2, qui dispose d’une solution de contournement.

Scénario

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de la fonction pyspark.sql.functions.log2 qui génère cet EWI. Dans cet exemple, la fonction log2 est utilisée pour calculer le logarithme base 2 de la colonne value.

df = spark.createDataFrame([(1,), (2,), (4,), (8,), (16,)], ["value"])
df_with_log2 = df.withColumn("log2_value", log2(df["value"]))
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1024 au code de sortie pour vous indiquer que cette fonction n’est pas directement prise en charge par Snowpark, mais qu’il existe une solution de contournement.

df = spark.createDataFrame([(1,), (2,), (4,), (8,), (16,)], ["value"])
#EWI: SPRKPY1024 => pyspark.sql.functions.log2 has a workaround, see documentation for more info
df_with_log2 = df.withColumn("log2_value", log2(df["value"]))
Copy

Correction recommandée

Pour contourner le problème, vous pouvez utiliser la fonction Snowflake.snowpark.functions.log en transmettant la valeur littérale 2 comme base.

df = session.createDataFrame([(1,), (2,), (4,), (8,), (16,)], ["value"])
df_with_log2 = df.withColumn("log2_value", log(2, df["value"]))
Copy

Recommandations supplémentaires

SPRKPY1086

Message : pyspark.ml.linalg.VectorUDT n’est pas pris en charge.

Catégorie : Avertissement

Description

pyspark.ml.linalg.VectorUDT n’est pas pris en charge.

Scénario

Code d’entrée

VectorUDT est un type de données permettant de représenter les colonnes d’un vecteur dans un DataFrame.

data = [
        (1, Vectors.dense([10.0, 20.0])),
        (2, Vectors.dense([25.0, 30.0])),
        (3, Vectors.dense([50.0, 60.0]))
    ]

schema = StructType([
        StructField("Id", IntegerType(), True),
        StructField("VectorCol", VectorUDT(), True),
    ])

df = SparkSession.createDataFrame(data, schema=schema)
Copy

Code de sortie

L’outil ajoute l’EWI SPRKPY1086 au code de sortie pour vous indiquer que cette fonction n’est pas prise en charge par Snowpark.

data = [
        (1, Vectors.dense([10.0, 20.0])),
        (2, Vectors.dense([25.0, 30.0])),
        (3, Vectors.dense([50.0, 60.0]))
    ]

#EWI: SPRKPY1086 => The pyspark.ml.linalg.VectorUDT function is not supported.
schema = StructType([
        StructField("Id", IntegerType(), True),
        StructField("VectorCol", VectorUDT(), True),
    ])

df = spark.createDataFrame(data, schema=schema)
Copy

Correction recommandée

pyspark.ml.linalg.VectorUDT n’a pas de correction recommandée.

Recommandations supplémentaires

SPRKPY1034

Avertissement

Ce code de problème est maintenant obsolète.

Message : pyspark.sql.functions.desc a une solution de contournement. Voir la documentation pour plus d’informations

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil SMA détecte une utilisation de la fonction pyspark.sql.functions.desc, qui dispose d’une solution de contournement.

Scénarios

La fonction pyspark.sql.functions.desc prend comme paramètre un objet de colonne ou le nom de la colonne sous forme de chaîne. Ces deux scénarios ne sont pas pris en charge par Snowpark. Par conséquent, cet EWI est généré.

Scénario 1

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de la fonction pyspark.sql.functions.desc qui prend comme paramètre un objet de colonne.

df.orderBy(desc(col))
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1034 au code de sortie pour vous indiquer que la fonction desc avec un paramètre d’objet de colonne n’est pas directement prise en charge par Snowpark, mais qu’il existe une solution de contournement.

#EWI: SPRKPY1034 => pyspark.sql.functions.desc has a workaround, see documentation for more info
df.orderBy(desc(col))
Copy

Correction recommandée

Comme solution de contournement, vous pouvez appeler la fonction snowflake.snowpark.Column.desc à partir du paramètre de la colonne.

df.orderBy(col.desc())
Copy
Scénario 2

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de la fonction pyspark.sql.functions.desc qui prend comme paramètre le nom de la colonne.

df.orderBy(desc("colName"))
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1034 au code de sortie pour vous indiquer que la fonction desc avec un paramètre de nom de colonne n’est pas directement prise en charge par Snowpark, mais qu’il existe une solution de contournement.

#EWI: SPRKPY1034 => pyspark.sql.functions.desc has a workaround, see documentation for more info
df.orderBy(desc("colName"))
Copy

Correction recommandée

Comme solution de contournement, vous pouvez convertir le paramètre de chaîne en un objet colonne à l’aide de la fonction snowflake.snowpark.functions.col, puis appeler la fonction snowflake.snowpark.desc..

df.orderBy(col("colName").desc())
Copy

Recommandations supplémentaires

SPRKPY1065

Message : pyspark.context.SparkContext.broadcast ne s’applique pas car Snowflake utilise un mécanisme de clustering des données pour calculer les données.

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.context.SparkContext.broadcast, qui n’est pas nécessaire en raison de l’utilisation de data-clustering de Snowflake.

Code d’entrée

Dans cet exemple, une variable de diffusion est créée. Ces variables permettent de partager les données plus efficacement entre tous les nœuds.

sc = SparkContext(conf=conf_spark)

mapping = {1: 10001, 2: 10002}

bc = sc.broadcast(mapping)
Copy

Code de sortie

L’outil SMA ajoute un message EWI indiquant que la diffusion n’est pas nécessaire.

sc = conf_spark

mapping = {1: 10001, 2: 10002}
#EWI: SPRKPY1065 => The element does not apply since snowflake use data-clustering mechanism to compute the data.

bc = sc.broadcast(mapping)
Copy

Correction recommandée

Supprimez toute utilisation de pyspark.context.SparkContext.broadcast.

sc = conf_spark

mapping = {1: 10001, 2: 10002}
Copy

Recommandations supplémentaires

SPRKPY1051

Avertissement

Ce code de problème est obsolète depuis Spark Conversion Core Version 2.4.0

Message : pyspark.sql.session.SparkSession.Builder.master a une solution de contournement

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.session.SparkSession.Builder.master qui dispose d’une solution de contournement.

Scénario

Entrée

Voici un exemple de l’utilisation de la méthode builder.master pour définir l’URL du maître Spark pour qu’il se connecte en local à l’aide d’un noyau.

spark = SparkSession.builder.master("local[1]")
Copy

Sortie

L’outil ajoute l’EWI SPRKPY1051 indiquant qu’une solution de contournement peut être mise en œuvre.

#EWI: SPRKPY1051 => pyspark.sql.session.SparkSession.Builder.master has a workaround, see documentation for more info
spark = Session.builder.master("local[1]")
Copy

Correction recommandée

pyspark.sql.session.SparkSession.Builder.master est utilisé pour configurer un cluster Spark. Snowpark n’utilise pas de clusters Spark, vous pouvez donc supprimer ou commenter le code.

## spark = Session.builder.master("local[1]")
Copy

Recommandations supplémentaires

SPRKPY1000

Message : La version spark-core du projet source est xx.xx:xx.x.x, la version spark-core prise en charge par Snowpark est 2.12:3.1.2. Il peut donc y avoir des différences de fonctionnalité entre les mappages existants.

Catégorie : Avertissement

Description

Ce problème apparaît lorsque la version Pyspark de votre code source n’est pas prise en charge. Cela signifie qu’il peut y avoir des différences fonctionnelles entre les mappages existants.

Recommandations supplémentaires

  • La version pyspark analysée par SMA pour la compatibilité avec Snowpark est comprise entre 2.12 et 3.1.2. Si vous utilisez une version en dehors de cette plage, l’outil peut produire des résultats incohérents. Vous pourriez modifier la version du code source que vous analysez.

  • Pour plus d’assistance, vous pouvez nous envoyer un e-mail à sma-support@snowflake.com ou signaler un problème dans l’outil SMA.

SPRKPY1081

Ce code de problème est obsolète depuis Spark Conversion Core 4.12.0

Message : pyspark.sql.readwriter.DataFrameWriter.partitionBy a une solution de contournement.

Catégorie : Avertissement

Description

La fonction Pyspark.sql.readwriter.DataFrameWriter.partitionBy n’est pas prise en charge. La solution consiste à utiliser la méthode copy_into_location de Snowpark à la place. Consultez la documentation pour plus d’informations.

Scénario

Entrée

Ce code créera un répertoire distinct pour chaque valeur unique de la colonne FIRST_NAME. Les données sont les mêmes, mais elles seront stockées dans des répertoires différents en fonction de la colonne.

df = session.createDataFrame([["John", "Berry"], ["Rick", "Berry"], ["Anthony", "Davis"]], schema = ["FIRST_NAME", "LAST_NAME"])
df.write.partitionBy("FIRST_NAME").csv("/home/data")
Copy

Ce code créera un répertoire distinct pour chaque valeur unique de la colonne FIRST_NAME. Les données sont les mêmes, mais elles seront stockées dans des répertoires différents en fonction de la colonne.

Code de sortie

df = session.createDataFrame([["John", "Berry"], ["Rick", "Berry"], ["Anthony", "Davis"]], schema = ["FIRST_NAME", "LAST_NAME"])
#EWI: SPRKPY1081 => The partitionBy function is not supported, but you can instead use copy_into_location as workaround. See the documentation for more info.
df.write.partitionBy("FIRST_NAME").csv("/home/data", format_type_options = dict(compression = "None"))
Copy

Correction recommandée

Dans Snowpark, copy_into_location dispose d’un paramètre partition_by que vous pouvez utiliser à la place de la fonction partitionBy, mais cela va nécessiter quelques ajustements manuels, comme le montre l’exemple suivant :

Code Spark :

df = session.createDataFrame([["John", "Berry"], ["Rick", "Berry"], ["Anthony", "Davis"]], schema = ["FIRST_NAME", "LAST_NAME"])
df.write.partitionBy("FIRST_NAME").csv("/home/data")
Copy

Code Snowpark ajusté manuellement :

df = session.createDataFrame([["John", "Berry"], ["Rick", "Berry"], ["Anthony", "Davis"]], schema = ["FIRST_NAME", "LAST_NAME"])
df.write.copy_into_location(location=temp_stage, partition_by=col("FIRST_NAME"), file_format_type="csv", format_type_options={"COMPRESSION": "NONE"}, header=True)
Copy

copy_into_location a les paramètres suivants.

  • Emplacement : L’emplacement Snowpark n’accepte que les emplacements Cloud utilisant une zone de préparation Snowflake.

  • partition_by : Il peut s’agir d’un nom de colonne ou d’une expression SQL. Vous devez donc effectuer une conversion en colonne ou en expression SQL en utilisant col ou sql_expr.

Recommandations supplémentaires

SPRKPY1072

Message : L’utilisation de StorageLevel n’est pas requise dans Snowpark.

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de la classe StorageLevel qui fonctionne comme des « indicateurs » pour définir le niveau de stockage. Étant donné que Snowflake contrôle le stockage, l’utilisation de cette fonction n’est pas requise.

Recommandations supplémentaires

SPRKPY1023

Message : pyspark.sql.functions.log1p a une solution de contournement. Voir la documentation pour plus d’informations

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil SMA détecte une utilisation de la fonction pyspark.sql.functions.log1p, qui dispose d’une solution de contournement.

Scénario

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de la fonction pyspark.sql.functions.log1p qui génère cet EWI. Dans cet exemple, la fonction log1p est utilisée pour calculer le logarithme naturel de la colonne value.

df = spark.createDataFrame([(0,), (1,), (10,), (100,)], ["value"])
df_with_log1p = df.withColumn("log1p_value", log1p(df["value"]))
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1023 au code de sortie pour vous indiquer que cette fonction n’est pas directement prise en charge par Snowpark, mais qu’il existe une solution de contournement.

df = spark.createDataFrame([(0,), (1,), (10,), (100,)], ["value"])
#EWI: SPRKPY1023 => pyspark.sql.functions.log1p has a workaround, see documentation for more info
df_with_log1p = df.withColumn("log1p_value", log1p(df["value"]))
Copy

Correction recommandée

Pour contourner le problème, vous pouvez utiliser la fonction call_function en transférant la chaîne ln comme premier argument et en ajoutant 1 au deuxième argument.

df = spark.createDataFrame([(0,), (1,), (10,), (100,)], ["value"])
df_with_log1p = df.withColumn("log1p_value", call_function("ln", lit(1) + df["value"]))
Copy

Recommandations supplémentaires

SPRKPY1017

Avertissement

Ce code de problème est obsolète depuis Spark Conversion Core Version 4.8.0

pyspark.sql.functions.date_add a une solution de contournement

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.functions.date_add qui dispose d’une solution de contournement.

Scénario

Entrée

Dans cet exemple, nous utilisons date_add pour calculer la date 5 jours après la date actuelle pour le dataframe df.

col = df.select(date_add(df.colName, 5))
Copy

Sortie

SMA renvoie l’EWI SPRKPY1017 sur la ligne où date_add est utilisé, ce qui vous permet d’identifier l’endroit à corriger.

#EWI: SPRKPY1017 => pyspark.sql.functions.date_add has a workaround, see documentation for more info
col = df.select(date_add(df.colName, 5))
Copy

Correction recommandée

Importez snowflake.snowpark.functions, qui contient une implémentation pour la fonction date_add (et son alias dateAdd).

from snowflake.snowpark.functions import date_add

col = df.select(date_add(df.dt, 1))
Copy

Recommandation supplémentaire

SPRKPY1046

Avertissement

Ce code de problème est obsolète depuis Spark Conversion Core Version 2.1.22

Message : pyspark.sql.functions.monotonically_increasing_id a une solution de contournement

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.functions.monotonically_increasing_id qui dispose d’une solution de contournement.

Scénario

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de la méthode monotonically_increasing_id.

from pyspark.sql import functions as F

spark.range(0, 10, 1, 2).select(F.monotonically_increasing_id()).show()
Copy

Sortie

L’outil ajoute l’EWI SPRKPY1046 indiquant qu’une solution de contournement peut être mise en œuvre.

from pyspark.sql import functions as F
#EWI: SPRKPY1046 => pyspark.sql.functions.monotonically_increasing_id has a workaround, see documentation for more info
spark.range(0, 10, 1, 2).select(F.monotonically_increasing_id()).show()
Copy

Correction recommandée

Mettez à jour la version de l’outil.

Recommandations supplémentaires

SPRKPY1056

Avertissement

Ce code de problème est maintenant obsolète.

Message : pyspark.sql.readwriter.DataFrameReader.option argument _ <argument_name> _ n’est pas un littéral et ne peut pas être évalué

Catégorie : Avertissement

Description

Ce problème apparaît lorsque la clé ou la valeur de l’argument de la fonction pyspark.sql.readwriter.DataFrameReader.option n’est pas une valeur littérale (par exemple une variable). L’outil SMA effectue une analyse statique de votre code source et il n’est donc pas possible d’évaluer le contenu de l’argument.

Scénario

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de la fonction pyspark.sql.readwriter.DataFrameReader.option qui génère cet EWI.

my_value = ...
my_option = ...

df1 = spark.read.option("dateFormat", my_value).format("csv").load('filename.csv')
df2 = spark.read.option(my_option, "false").format("csv").load('filename.csv')
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1056 au code de sortie pour vous indiquer que l’argument de cette fonction n’est pas une valeur littérale et, par conséquent, qu’il n’a pas pu être évalué par SMA.

my_value = ...
my_option = ...

#EWI: SPRKPY1056 => pyspark.sql.readwriter.DataFrameReader.option argument "dateFormat" is not a literal and can't be evaluated
df1 = spark.read.option("dateFormat", my_value).format("csv").load('filename.csv')
#EWI: SPRKPY1056 => pyspark.sql.readwriter.DataFrameReader.option argument key is not a literal and can't be evaluated
df2 = spark.read.option(my_option, "false").format("csv").load('filename.csv')
Copy

Correction recommandée

Même si l’outil SMA n’a pas été en mesure d’évaluer l’argument, cela ne signifie pas qu’il n’est pas pris en charge par Snowpark. Veuillez vous assurer que la valeur de l’argument est valide et équivalente dans Snowpark en consultant la documentation.

Recommandations supplémentaires

SPRKPY1007

Avertissement

Ce code de problème est obsolète depuis Spark Conversion Core Version 4.8.0

Messagee ** :** pyspark.sql.context.SQLContext n’est pas nécessaire

Catégoriey ** :** Avertissement.

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.context.SQLContext.set qui n’est pas requis.

Scénario

Entrée

Voici un exemple avec différentes surcharges SparkContext.

from pyspark import SQLContext

my_sc1 = SQLContext(myMaster, myAppName, mySparkHome, myPyFiles, myEnvironment, myBatctSize, mySerializer, my_conf1)
my_sc2 = SQLContext(conf=my_conf2)
my_sc3 = SQLContext()
Copy

Sortie

Le code de sortie a commenté la ligne pour pyspark.SQLContext, et remplace les scénarios par une référence à une configuration. Notez que les variables my_sc1 et my_sc2 qui contiennent les propriétés Spark peuvent ne pas être nécessaires ou devront être adaptées pour corriger le code.

#EWI: SPRKPY1007 => pyspark.sql.context.SQLContext is not required
#from pyspark import SQLContext
pass

#EWI: SPRKPY1007 => pyspark.sql.context.SQLContext is not required
sql_context1 = my_sc1
#EWI: SPRKPY1007 => pyspark.sql.context.SQLContext is not required
sql_context2 = my_sc2
Copy

Recommandations supplémentaires

  • Il s’agit d’un paramètre inutile qui est supprimé et pour lequel un commentaire d’avertissement a été inséré dans le code source. L’utilisateur ne doit effectuer aucune action.

  • Pour plus d’assistance, vous pouvez nous envoyer un e-mail à sma-support@snowflake.com ou signaler un problème dans l’outil SMA.

SPRKPY1033

Avertissement

Ce code de problème est maintenant obsolète.

Message : pyspark.sql.functions.asc a une solution de contournement. Voir la documentation pour plus d’informations

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil SMA détecte une utilisation de la fonction pyspark.sql.functions.asc, qui dispose d’une solution de contournement.

Scénarios

La fonction pyspark.sql.functions.asc prend comme paramètre un objet de colonne ou le nom de la colonne sous forme de chaîne. Ces deux scénarios ne sont pas pris en charge par Snowpark. Par conséquent, cet EWI est généré.

Scénario 1

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de la fonction pyspark.sql.functions.asc qui prend comme paramètre un objet de colonne.

df.orderBy(asc(col))
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1033 au code de sortie pour vous indiquer que la fonction asc avec un paramètre d’objet de colonne n’est pas directement prise en charge par Snowpark, mais qu’il existe une solution de contournement.

#EWI: SPRKPY1033 => pyspark.sql.functions.asc has a workaround, see documentation for more info
df.orderBy(asc(col))
Copy

Correction recommandée

Comme solution de contournement, vous pouvez appeler la fonction snowflake.snowpark.Column.asc à partir du paramètre de la colonne.

df.orderBy(col.asc())
Copy
Scénario 2

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de la fonction pyspark.sql.functions.asc qui prend comme paramètre le nom de la colonne.

df.orderBy(asc("colName"))
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1033 au code de sortie pour vous indiquer que la fonction asc avec un paramètre de nom de colonne n’est pas directement prise en charge par Snowpark, mais qu’il existe une solution de contournement.

#EWI: SPRKPY1033 => pyspark.sql.functions.asc has a workaround, see documentation for more info
df.orderBy(asc("colName"))
Copy

Correction recommandée

Comme solution de contournement, vous pouvez convertir le paramètre de chaîne en un objet colonne à l’aide de la fonction snowflake.snowpark.functions.col, puis appeler la fonction snowflake.snowpark.Column.asc.

df.orderBy(col("colName").asc())
Copy

Recommandations supplémentaires

SPRKPY1062

Message : Snowpark ne prend pas charge GroupedData.pivot sans le paramètre « values ».

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil SMA détecte l’utilisation de la fonction pyspark.sql.group.GroupedData.pivot sans le paramètre « values » (la liste des valeurs sur lesquelles pivoter).

Pour l’instant, la fonction pivot de Snowpark Python vous oblige à spécifier explicitement la liste des valeurs distinctes sur lesquelles pivoter.

Scénarios

Scénario 1

Entrée

L’outil SMA détecte une expression qui correspond au modèle dataFrame.groupBy("columnX").pivot("columnY") et le pivot n’a pas le paramètre values.

df.groupBy("date").pivot("category").sum("amount")
Copy

Sortie

L’outil SMA ajoute un message EWI indiquant que la fonction pivot sans le paramètre « values » n’est pas prise en charge.

En outre, il ajoutera comme deuxième paramètre de la fonction pivot une compréhension de liste qui calcule la liste des valeurs qui seront traduites en colonnes. Gardez à l’esprit que cette opération n’est pas efficace pour les grands ensembles de données, et qu’il est conseillé d’indiquer les valeurs de manière explicite.

#EWI: SPRKPY1062 => pyspark.sql.group.GroupedData.pivot without parameter 'values' is not supported. See documentation for more info.
df.groupBy("date").pivot("category", [v[0] for v in df.select("category").distinct().limit(10000).collect()]]).sum("amount")
Copy

Correction recommandée

Pour ce scénario, l’outil SMA ajoute comme deuxième paramètre de la fonction pivot une compréhension de liste qui calcule la liste des valeurs qui seront traduites en colonnes, mais vous pouvez également utiliser une liste de valeurs distinctes sur lesquelles pivoter, comme suit :

df = spark.createDataFrame([
      Row(category="Client_ID", date=2012, amount=10000),
      Row(category="Client_name",   date=2012, amount=20000)
  ])

df.groupBy("date").pivot("category", ["dotNET", "Java"]).sum("amount")
Copy
Scénario 2

Entrée

L’outil SMA n’a pas pu détecter une expression qui correspond au modèle dataFrame.groupBy("columnX").pivot("columnY") et le pivot n’a pas le paramètre values.

df1.union(df2).groupBy("date").pivot("category").sum("amount")
Copy

Sortie

L’outil SMA ajoute un message EWI indiquant que la fonction pivot sans le paramètre « values » n’est pas prise en charge.

#EWI: SPRKPY1062 => pyspark.sql.group.GroupedData.pivot without parameter 'values' is not supported. See documentation for more info.
df1.union(df2).groupBy("date").pivot("category").sum("amount")
Copy

Correction recommandée

Ajoutez une liste de valeurs distinctes sur lesquelles pivoter, comme suit :

df = spark.createDataFrame([
      Row(course="dotNET", year=2012, earnings=10000),
      Row(course="Java",   year=2012, earnings=20000)
  ])

df.groupBy("year").pivot("course", ["dotNET", "Java"]).sum("earnings").show()
Copy

Recommandations supplémentaires

  • Le calcul de la liste des valeurs distinctes sur lesquelles pivoter n’est pas une opération efficace sur les grands ensembles de données et pourrait se transformer en appel bloquant. Veuillez envisager d’indiquer explicitement la liste des valeurs distinctes sur lesquelles pivoter.

  • Si vous ne souhaitez pas spécifier explicitement la liste des valeurs distinctes sur lesquelles pivoter (ce qui n’est pas conseillé), vous pouvez ajouter le code suivant comme deuxième argument de la fonction pivot pour déduire les valeurs au moment de l’exécution*

[v[0] for v in <df>.select(<column>).distinct().limit(<count>).collect()]]
Copy

*_ Remplacez _ <df> par le DataFrame correspondant, par la colonne à pivoter et par le nombre de lignes à sélectionner.

SPRKPY1042

Message : pyspark.sql.functions.posexplode a une solution de contournement

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.functions.posexplode qui dispose d’une solution de contournement.

Scénarios

Cette méthode peut traiter plusieurs scénarios en fonction du type de colonne passé sous forme de paramètre : il peut s’agir d’une liste de valeurs ou d’une carte/d'un répertoire (clés/valeurs).

Scénario 1

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de la méthode posexplode passant sous forme de paramètre d’une liste de valeurs.

df = spark.createDataFrame(
    [Row(a=1,
         intlist=[1, 2, 3])])

df.select(posexplode(df.intlist)).collect()
Copy

Sortie

L’outil ajoute l’EWI SPRKPY1042 indiquant qu’une solution de contournement peut être mise en œuvre.

df = spark.createDataFrame(
    [Row(a=1,
         intlist=[100, 200, 300])])
#EWI: SPRKPY1042 => pyspark.sql.functions.posexplode has a workaround, see documentation for more info

df.select(posexplode(df.intlist)).show()
Copy

Correction recommandée

Pour obtenir le même comportement, utilisez la méthode functions.flatten, supprimez les colonnes supplémentaires et renommez les noms des colonnes d’index et de valeurs.

df = spark.createDataFrame(
  [Row(a=1,
       intlist=[1, 2, 3])])

df.select(
    flatten(df.intlist))\
    .drop("DATA", "SEQ", "KEY", "PATH", "THIS")\
    .rename({"INDEX": "pos", "VALUE": "col"}).show()
Copy
Scénario 2

Entrée

Vous trouverez ci-dessous un autre exemple d’utilisation de posexplode passant sous forme de paramètre une carte/un dictionnaire (clés/valeurs)

df = spark.createDataFrame([
    [1, [1, 2, 3], {"Ashi Garami": "Single Leg X"}, "Kimura"],
    [2, [11, 22], {"Sankaku": "Triangle"}, "Coffee"]
],
schema=["idx", "lists", "maps", "strs"])

df.select(posexplode(df.maps)).show()
Copy

Sortie

L’outil ajoute l’EWI SPRKPY1042 indiquant qu’une solution de contournement peut être mise en œuvre.

df = spark.createDataFrame([
    [1, [1, 2, 3], {"Ashi Garami": "Single Leg X"}, "Kimura"],
    [2, [11, 22], {"Sankaku": "Triangle"}, "Coffee"]
],
schema=["idx", "lists", "maps", "strs"])
#EWI: SPRKPY1042 => pyspark.sql.functions.posexplode has a workaround, see documentation for more info

df.select(posexplode(df.maps)).show()
Copy

Correction recommandée

Pour contourner le problème, vous pouvez utiliser functions.row_number pour obtenir la position et functions.explode avec le nom du champ pour obtenir la valeur de la clé/valeur pour les dictionnaires.

df = spark.createDataFrame([
    [10, [1, 2, 3], {"Ashi Garami": "Single Leg X"}, "Kimura"],
    [11, [11, 22], {"Sankaku": "Triangle"}, "Coffee"]
],
    schema=["idx", "lists", "maps", "strs"])

window = Window.orderBy(col("idx").asc())

df.select(
    row_number().over(window).alias("pos"),
    explode(df.maps).alias("key", "value")).show()
Copy

Remarque : l’utilisation de row_number n’est pas totalement équivalent, car il commence par 1 (et non par zéro comme dans la méthode Spark)

Recommandations supplémentaires

SPRKPY1013

Message : pyspark.sql.functions.acosh a une solution de contournement

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.functions.acosh qui dispose d’une solution de contournement.

Scénario

Entrée

Dans cet exemple, pyspark calcule acosh pour un dataframe à l’aide de pyspark.sql.functions.acosh.

from pyspark.sql import SparkSession
from pyspark.sql.functions import acosh
spark = SparkSession.builder.getOrCreate()
data = [['V1', 30],
        ['V2', 60],
        ['V3', 50],
        ['V4', 13]]

columns = ['Paremeter', 'value']
df = spark.createDataFrame(data, columns)
df_with_acosh = df.withColumn("acosh_value", acosh(df["value"]))
Copy

Sortie

SMA renvoie l’EWI SPRKPY1013 sur la ligne où acosh est utilisé, ce qui vous permet d’identifier l’endroit à corriger.

from snowflake.snowpark import Session

spark = Session.builder.getOrCreate()
spark.update_query_tag({"origin":"sf_sit","name":"sma","version":{"major":0,"minor":0,"patch":0},"attributes":{"language":"Python"}})
data = [['V1', 30],
        ['V2', 60],
        ['V3', 50],
        ['V4', 13]]

columns = ['Paremeter', 'value']
df = spark.createDataFrame(data, columns)
#EWI: SPRKPY1013 => pyspark.sql.functions.acosh has a workaround, see documentation for more info
df_with_acosh = df.withColumn("acosh_value", acosh(df["value"]))
Copy

Correction recommandée

Il n’y a pas d’implémentation « acosh » directe, mais on peut utiliser « call_function » à la place, et utiliser « acosh » comme premier paramètre et colName comme second.

import snowflake.snowpark as snowpark
from snowflake.snowpark import Session
from snowflake.snowpark.functions import call_function, col

spark = Session.builder.getOrCreate()
spark.update_query_tag({"origin":"sf_sit","name":"sma","version":{"major":0,"minor":0,"patch":0},"attributes":{"language":"Python"}})
data = [['V1', 30],
        ['V2', 60],
        ['V3', 50],
        ['V4', 13]]

columns = ['Paremeter', 'value']
df = spark.createDataFrame(data, columns)
df_with_acosh = df.select(call_function('ACOSH', col('value')))
Copy

Recommandations supplémentaires

SPRKPY1085

Message : pyspark.ml.feature.VectorAssembler n’est pas pris en charge.

Catégorie : Avertissement

Description

pyspark.ml.feature.VectorAssembler n’est pas pris en charge.

Scénario

Code d’entrée

VectorAssembler est utilisé pour combiner plusieurs colonnes en un seul vecteur.

data = [
        (1, 10.0, 20.0),
        (2, 25.0, 30.0),
        (3, 50.0, 60.0)
    ]

df = SparkSession.createDataFrame(data, schema=["Id", "col1", "col2"])
vector = VectorAssembler(inputCols=["col1", "col2"], output="cols")
Copy

Code de sortie

L’outil ajoute l’EWI SPRKPY1085 au code de sortie pour vous indiquer que cette classe n’est pas prise en charge par Snowpark.

data = [
        (1, 10.0, 20.0),
        (2, 25.0, 30.0),
        (3, 50.0, 60.0)
    ]

df = spark.createDataFrame(data, schema=["Id", "col1", "col2"])
#EWI: SPRKPY1085 => The pyspark.ml.feature.VectorAssembler function is not supported.

vector = VectorAssembler(inputCols=["col1", "col2"], output="cols")
Copy

Correction recommandée

pyspark.ml.feature.VectorAssembler n’a pas de correction recommandée.

Recommandations supplémentaires

SPRKPY1027

Avertissement

Ce code de problème est obsolète depuis Spark Conversion Core 4.5.2

Message : pyspark.sql.readwriter.DataFrameReader.json a une solution de contournement. Voir la documentation pour plus d’informations

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil SMA détecte une utilisation de la fonction pyspark.sql.readwriter.DataFrameReader.json, qui dispose d’une solution de contournement.

Scénario

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de la fonction pyspark.sql.readwriter.DataFrameReader.json qui génère cet EWI. Dans cet exemple, la fonction json est utilisée pour lire plusieurs fichiers .json avec un schéma donné et utilise quelques options supplémentaires telles que primitiveAsString et dateFormat pour affiner le comportement de lecture des fichiers.

file_paths = [
  "path/to/your/file1.json",
  "path/to/your/file2.json",
  "path/to/your/file3.json",
]

df = session.read.json(
  file_paths,
  schema=my_schema,
  primitiveAsString=True,
  dateFormat="2023-06-20"
)
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1027 au code de sortie pour vous indiquer que cette fonction n’est pas directement prise en charge par Snowpark, mais qu’il existe une solution de contournement.

file_paths = [
  "path/to/your/file1.json",
  "path/to/your/file2.json",
  "path/to/your/file3.json",
]

#EWI: SPRKPY1027 => pyspark.sql.readwriter.DataFrameReader.json has a workaround, see documentation for more info
df = session.read.json(
  file_paths,
  schema=my_schema,
  primitiveAsString=True,
  dateFormat="2023-06-20"
)
Copy

Correction recommandée

Dans cette section, nous expliquons comment configurer le paramètre path, le paramètre schema et certaines options pour les faire fonctionner dans Snowpark.

1. Paramètre path

Snowpark exige que le paramètre path soit un emplacement de zone de préparation. Pour contourner le problème, vous pouvez créer une zone de préparation temporaire et ajouter chaque fichier .json à cette zone de préparation en utilisant le préfixe file://.

2. Paramètre schema

Snowpark ne permet pas de définir schema comme paramètre de la fonction json. En guise de solution de contournement, vous pouvez utiliser la fonction snowflake.snowpark.DataFrameReader.schema.

3. Paramètres des options

Snowpark ne permet pas de définir les options supplémentaires comme paramètres de la fonction json. Comme solution de contournement, vous pouvez utiliser la fonction Snowflake.snowpark.DataFrameReader.option pour spécifier ces paramètres en tant qu’options de DataFrameReader.

Note

Les options suivantes ne sont pas prises en charge par Snowpark :

  • allowBackslashEscapingAnyCharacter

  • allowComments

  • allowNonNumericNumbers

  • allowNumericLeadingZero

  • allowSingleQuotes

  • allowUnquotedControlChars

  • allowUnquotedFieldNames

  • columnNameOfCorruptRecord

  • dropFiledIfAllNull

  • encoding

  • ignoreNullFields

  • ligneSep

  • locale

  • mode

  • multiline

  • prefersDecimal

  • primitiveAsString

  • samplingRatio

  • timestampNTZFormat

  • timeZone

Vous trouverez ci-dessous l’exemple complet de ce à quoi devrait ressembler le code d’entrée après avoir appliqué les suggestions mentionnées ci-dessus pour qu’il fonctionne dans Snowpark :

stage = f'{session.get_fully_qualified_current_schema()}.{_generate_prefix("TEMP_STAGE")}'
session.sql(f'CREATE TEMPORARY STAGE IF NOT EXISTS {stage}')

session.file.put(f"file:///path/to/your/file1.json", f"@{stage}")
session.file.put(f"file:///path/to/your/file2.json", f"@{stage}")
session.file.put(f"file:///path/to/your/file3.json", f"@{stage}")

df = session.read.schema(my_schema).option("dateFormat", "2023-06-20").json(stage)
Copy

Recommandations supplémentaires

SPRKPY1076

Message : Les paramètres des méthodes pyspark.sql.readwriter.DataFrameReader ne sont pas pris en charge. Ceci s’applique aux méthodes CSV, JSON et PARQUET.

Catégorie : Avertissement

Description

Pour les méthodes CSV, JSON et PARQUET sur l’objet pyspark.sql.readwriter.DataFrameReader, l’outil va analyser les paramètres et ajouter une transformation en fonction de chaque cas :

  • Tous les paramètres correspondent à leur nom équivalent dans Snowpark : dans ce cas, l’outil transformera le paramètre en un appel .option(). Dans ce cas, le paramètre n’ajoutera pas cet EWI.

  • Certains paramètres ne correspondent pas à l’équivalent dans Snowpark : dans ce cas, l’outil ajoutera cet EWI avec les informations sur le paramètre et le supprimera de l’appel de la méthode.

Liste des équivalences :

  • Équivalences pour CSV :

Clés Spark

Equivalences Snowpark

sep

FIELD_DELIMITER

header

PARSE_HEADER

ligneSep

RECORD_DELIMITER

pathGlobFilter

PATTERN

quote

FIELD_OPTIONALLY_ENCLOSED_BY

nullValue

NULL_IF

dateFormat

DATE_FORMAT

timestampFormat

TIMESTAMP_FORMAT

inferSchema

INFER_SCHEMA

delimiter

FIELD_DELIMITER

  • Équivalences pour JSON :

Clés Spark

Equivalences Snowpark

dateFormat

DATE_FORMAT

timestampFormat

TIMESTAMP_FORMAT

pathGlobFilter

PATTERN

  • Équivalences pour PARQUET :

Clés Spark

Equivalences Snowpark

pathGlobFilter

PATTERN

Scénarios

Scénario 1

Entrée

Pour CVS, voici quelques exemples :

from pyspark.sql import SparkSession

spark = SparkSession.builder.appName('myapp').getOrCreate()

spark.read.csv("path3", None,None,None,None,None,None,True).show()
Copy

Sortie

Dans le code converti, les paramètres sont ajoutés en tant qu’options individuelles à la fonction cvs

from snowflake.snowpark import Session

spark = Session.builder.app_name('myapp', True).getOrCreate()
spark.update_query_tag({"origin":"sf_sit","name":"sma","version":{"major":0,"minor":0,"patch":0},"attributes":{"language":"Python"}})

#EWI: SPRKPY1076 => Some of the included parameters are not supported in the csv function, the supported ones will be added into a option method.
spark.read.option("FIELD_DELIMITER", None).option("PARSE_HEADER", True).option("FIELD_OPTIONALLY_ENCLOSED_BY", None).csv("path3").show()
Copy

Scénario 2

Entrée

Pour JSON, voici quelques exemples :

from pyspark.sql import SparkSession
spark = SparkSession.builder.appName('myapp').getOrCreate()
spark.read.json("/myPath/jsonFile/", dateFormat='YYYY/MM/DD').show()
Copy

Sortie

Dans le code converti, les paramètres sont ajoutés en tant qu’options individuelles à la fonction json

from snowflake.snowpark import Session
spark = Session.builder.app_name('myapp', True).getOrCreate()
#EWI: SPRKPY1076 => Some of the included parameters are not supported in the json function, the supported ones will be added into a option method.

spark.read.option("DATE_FORMAT", 'YYYY/MM/DD').json("/myPath/jsonFile/").show()
Copy
Scénario 3

Entrée

Pour PARQUET, voici quelques exemples :

from pyspark.sql import SparkSession
spark = SparkSession.builder.appName('myapp').getOrCreate()

spark.read.parquet("/path/to/my/file.parquet", pathGlobFilter="*.parquet").show()
Copy

Sortie

Dans le code converti, les paramètres sont ajoutés en tant qu’options individuelles à la fonction Parquet

from snowflake.snowpark import Session

spark = Session.builder.app_name('myapp', True).getOrCreate()
spark.update_query_tag({"origin":"sf_sit","name":"sma","version":{"major":0,"minor":0,"patch":0},"attributes":{"language":"Python"}})

#EWI: SPRKPY1076 => Some of the included parameters are not supported in the parquet function, the supported ones will be added into a option method.
#EWI: SPRKPY1029 => The parquet function require adjustments, in Snowpark the parquet files needs to be located in an stage. See the documentation for more info.

spark.read.option("PATTERN", "*.parquet").parquet("/path/to/my/file.parquet")
Copy

Recommandations supplémentaires

SPRKPY1066

Message : L’élément Spark ne s’applique pas car Snowflake utilise le mécanisme de micro-partitionnement qui est créé automatiquement.

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation d’éléments liés aux partitions :

Ces éléments ne s’appliquent pas en raison de l’utilisation de micro-partitions de Snowflake.

Code d’entrée

Dans cet exemple sortWithinPartitions, il est utilisé pour créer une partition dans un DataFrame trié selon la colonne spécifiée.

df = spark.createDataFrame([(2, "Alice"), (5, "Bob")], schema=["age", "name"])
df.sortWithinPartitions("age", ascending=False)
Copy

Code de sortie

L’outil SMA ajoute un EWI indiquant que l’élément Spark n’est pas requis.

df = spark.createDataFrame([(2, "Alice"), (5, "Bob")], schema=["age", "name"])
#EWI: SPRKPY1066 => The element does not apply since snowflake use micro-partitioning mechanism are created automatically.
df.sortWithinPartitions("age", ascending=False)
Copy

Correction recommandée

Supprimez l’utilisation de l’élément.

df = spark.createDataFrame([(2, "Alice"), (5, "Bob")], schema=["age", "name"])
Copy

Recommandations supplémentaires

SPRKPY1037

Avertissement

Ce code de problème est maintenant obsolète.

Message : pyspark.sql.functions.sort_array a une solution de contournement. Voir la documentation pour plus d’informations

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil SMA détecte une utilisation de la fonction pyspark.sql.functions.sort_array, qui dispose d’une solution de contournement.

Scénario

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de la fonction pyspark.sql.functions.sort_array qui génère cet EWI. Dans cet exemple, la fonction sort_array est utilisée pour trier le tableau numbers dans l’ordre croissant et décroissant.

df = spark.createDataFrame([(1, [3, 1, 2]), (2, [10, 5, 8]), (3, [6, 4, 7])], ["id", "numbers"])
df_sorted_asc = df.withColumn("sorted_numbers_asc", sort_array("numbers", asc=True))
df_sorted_desc = df.withColumn("sorted_numbers_desc", sort_array("numbers", asc=False))
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1037 au code de sortie pour vous indiquer que cette fonction n’est pas directement prise en charge par Snowpark, mais qu’il existe une solution de contournement.

df = spark.createDataFrame([(1, [3, 1, 2]), (2, [10, 5, 8]), (3, [6, 4, 7])], ["id", "numbers"])
#EWI: SPRKPY1037 => pyspark.sql.functions.sort_array has a workaround, see documentation for more info
df_sorted_asc = df.withColumn("sorted_numbers_asc", sort_array("numbers", asc=True))
#EWI: SPRKPY1037 => pyspark.sql.functions.sort_array has a workaround, see documentation for more info
df_sorted_desc = df.withColumn("sorted_numbers_desc", sort_array("numbers", asc=False))
Copy

Correction recommandée

Pour contourner le problème, vous pouvez importer le paquet snowpark_extensions qui fournit une extension pour la fonction sort_array.

import snowpark_extensions

df = spark.createDataFrame([(1, [3, 1, 2]), (2, [10, 5, 8]), (3, [6, 4, 7])], ["id", "numbers"])
df_sorted_asc = df.withColumn("sorted_numbers_asc", sort_array("numbers", asc=True))
df_sorted_desc = df.withColumn("sorted_numbers_desc", sort_array("numbers", asc=False))
Copy

Recommandations supplémentaires

SPRKPY1003

Messagee ** :** Une erreur s’est produite lors du chargement de la table des symboles.

Catégoriey ** :** Erreur de conversion.

Description

Ce problème apparaît en cas d’erreur de traitement des symboles dans la table des symboles. La table des symboles fait partie de l’architecture sous-jacente de l’outil SMA, ce qui permet des conversions plus complexes. Cette erreur peut être due à une instruction inattendue dans le code source.

Recommandations supplémentaires

  • Il est peu probable qu’il s’agisse d’une erreur dans le code source lui-même, mais plutôt d’une erreur dans la manière dont l’outil traite le code source. La meilleure solution serait de signaler un problème dans l’outil SMA.

  • Pour plus d’assistance, vous pouvez nous envoyer un e-mail à sma-support@snowflake.com ou signaler un problème dans l’outil SMA.

SPRKPY1052

Avertissement

Ce code de problème est obsolète depuis Spark Conversion Core Version 2.8.0

Message : pyspark.sql.session.SparkSession.Builder.enableHiveSupport a une solution de contournement

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.session.SparkSession.Builder.enableHiveSupport qui dispose d’une solution de contournement.

Scénario

Entrée

Vous trouverez ci-dessous un exemple de configuration de SparkSession et d’activation de la prise en charge Hive à l’aide de la méthode enableHiveSupport.

spark = Session.builder.appName("Merge_target_table")\
        .config("spark.port.maxRetries","100") \
        .enableHiveSupport().getOrCreate()
Copy

Sortie

L’outil ajoute l’EWI SPRKPY1052 indiquant qu’une solution de contournement peut être mise en œuvre.

#EWI: SPRKPY1052 => pyspark.sql.session.SparkSession.Builder.enableHiveSupport has a workaround, see documentation for more info
spark = Session.builder.appName("Merge_target_table")\
        .config("spark.port.maxRetries","100") \
        .enableHiveSupport().getOrCreate()
Copy

Correction recommandée

Supprimez l’utilisation de la fonction enableHiveSupport car elle n’est pas nécessaire dans Snowpark.

spark = Session.builder.appName("Merge_target_table")\
        .config("spark.port.maxRetries","100") \
        .getOrCreate()
Copy

Recommandations supplémentaires

SPRKPY1043

Message : pyspark.sql.functions.posexplode_outer a une solution de contournement

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.functions.posexplode_outer qui dispose d’une solution de contournement.

Scénarios

Cette méthode peut traiter plusieurs scénarios en fonction du type de colonne passé sous forme de paramètre : il peut s’agir d’une liste de valeurs ou d’une carte/d'un répertoire (clés/valeurs).

Scénario 1

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de la méthode posexplode_outer en transférant une liste de valeurs.

df = spark.createDataFrame(
    [
        (1, ["foo", "bar"]),
        (2, []),
        (3, None)],
    ("id", "an_array"))

df.select("id", "an_array", posexplode_outer("an_array")).show()
Copy

Sortie

L’outil ajoute l’EWI SPRKPY1043 indiquant qu’une solution de contournement peut être mise en œuvre.

df = spark.createDataFrame(
    [
        (1, ["foo", "bar"]),
        (2, []),
        (3, None)],
    ("id", "an_array"))
#EWI: SPRKPY1043 => pyspark.sql.functions.posexplode_outer has a workaround, see documentation for more info

df.select("id", "an_array", posexplode_outer("an_array")).show()
Copy

Correction recommandée

Pour obtenir le même comportement, utilisez la méthode functions.flatten en envoyant le paramètre outer dans True, supprimez les colonnes supplémentaires et renommez les noms des colonnes d’index et de valeurs.

df = spark.createDataFrame(
    [
        (1, ["foo", "bar"]),
        (2, []),
        (3, None)],
    ("id", "an_array"))

df.select(
    flatten(df.an_array, outer=True))\
    .drop("DATA", "SEQ", "KEY", "PATH", "THIS")\
    .rename({"INDEX": "pos", "VALUE": "col"}).show()
Copy
Scénario 2

Entrée

Vous trouverez ci-dessous un autre exemple d’utilisation de posexplode_outer en transférant une carte/un dictionnaire (clés/valeurs)

df = spark.createDataFrame(
    [
        (1, {"x": 1.0}),
        (2, {}),
        (3, None)],
    ("id", "a_map"))

df.select(posexplode_outer(df.a_map)).show()
Copy

Sortie

L’outil ajoute l’EWI SPRKPY1043 indiquant qu’une solution de contournement peut être mise en œuvre.

df = spark.createDataFrame(
    [
        (1, {"x": "Ashi Garami"}),
        (2, {}),
        (3, None)],
    ("id", "a_map"))
#EWI: SPRKPY1043 => pyspark.sql.functions.posexplode_outer has a workaround, see documentation for more info

df.select(posexplode_outer(df.a_map)).show()
Copy

Correction recommandée

Pour contourner le problème, vous pouvez utiliser functions.row_number pour obtenir la position et functions.explode_outer avec le nom du champ pour obtenir la valeur de la clé/valeur pour les dictionnaires.

df = spark.createDataFrame(
    [
        (1, {"x": "Ashi Garami"}),
        (2,  {}),
        (3, None)],
    ("id", "a_map"))

window = Window.orderBy(col("id").asc())

df.select(
    row_number().over(window).alias("pos"),
          explode_outer(df.a_map)).show()
Copy

Remarque : l’utilisation de row_number n’est pas totalement équivalent, car il commence par 1 (et non par zéro comme dans la méthode Spark)

Recommandations supplémentaires

SPRKPY1012

Avertissement

Ce code de problème est maintenant obsolète.

Message : pyspark.sql.dataframe.DataFrameStatFunctions.writeTo a une solution de contournement

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.dataframe.DataFrameStatFunctions.writeTo qui dispose d’une solution de contournement.

Scénario

Entrée

Pour cet exemple, le dataframe df est écrit dans une table Spark « table ».

writer = df.writeTo("table")
Copy

Sortie

SMA renvoie l’EWI SPRKPY1012 sur la ligne où DataFrameStatFunctions.writeTo est utilisé, ce qui vous permet d’identifier l’endroit à corriger.

#EWI: SPRKPY1012 => pyspark.sql.dataframe.DataFrameStatFunctions.writeTo has a workaround, see documentation for more info
writer = df.writeTo("table")
Copy

Correction recommandée

Au lieu de cela, utilisez df.write.SaveAsTable().

import df.write as wt
writer = df.write.save_as_table(table)
Copy

Recommandations supplémentaires

SPRKPY1084

Ce code de problème est obsolète depuis Spark Conversion Core 4.12.0

Message : pyspark.sql.readwriter.DataFrameWriter.option n’est pas pris en charge.

Catégorie : Avertissement

Description

La fonction pyspark.sql.readwriter.DataFrameWriter.option n’est pas prise en charge.

Scénario

Code d’entrée

Vous trouverez ci-dessous un exemple d’utilisation de la méthode option. Cette méthode est utilisée pour ajouter des configurations supplémentaires lors de l’écriture des données d’un DataFrame.

path_csv_file = "/path/to/file.csv"
data = [
        ("John", 30, "New York"),
        ("Jane", 25, "San Francisco")
    ]

df = spark.createDataFrame(data, schema=["Name", "Age", "City"])

df.write.option("header", True).csv(csv_file_path)
df.write.option("sep", ";").option("lineSep","-").csv(csv_file_path)
Copy

Code de sortie

L’outil ajoute l’EWI SPRKPY1084 au code de sortie pour vous indiquer que cette fonction n’est pas prise en charge par Snowpark.

path_csv_file = "/path/to/file.csv"
data = [
        ("John", 30, "New York"),
        ("Jane", 25, "San Francisco")
    ]

df = spark.createDataFrame(data, schema=["Name", "Age", "City"])

#EWI: SPRKPY1084 => The pyspark.sql.readwriter.DataFrameWriter.option function is not supported.

df.write.option("header", True).csv(csv_file_path)
#EWI: SPRKPY1084 => The pyspark.sql.readwriter.DataFrameWriter.option function is not supported.
df.write.option("sep", ";").option("lineSep","-").csv(csv_file_path)
Copy

Correction recommandée

La méthode pyspark.sql.readwriter.DataFrameWriter.option n’a pas de correction recommandée.

Recommandations supplémentaires

SPRKPY1026

Avertissement

Ce code de problème est obsolète depuis Spark Conversion Core 4.3.2

Message : pyspark.sql.readwriter.DataFrameReader.csv a une solution de contournement. Voir la documentation pour plus d’informations

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil SMA détecte une utilisation de la fonction pyspark.sql.readwriter.DataFrameReader.csv, qui dispose d’une solution de contournement.

Scénario

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de la fonction pyspark.sql.readwriter.DataFrameReader.csv qui génère cet EWI. Dans cet exemple, la fonction csv est utilisée pour lire plusieurs fichiers .csv avec un schéma donné et utilise quelques options supplémentaires telles que encoding, header et sep pour affiner le comportement de lecture des fichiers.

file_paths = [
  "path/to/your/file1.csv",
  "path/to/your/file2.csv",
  "path/to/your/file3.csv",
]

df = session.read.csv(
  file_paths,
  schema=my_schema,
  encoding="UTF-8",
  header=True,
  sep=","
)
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1026 au code de sortie pour vous indiquer que cette fonction n’est pas directement prise en charge par Snowpark, mais qu’il existe une solution de contournement.

file_paths = [
  "path/to/your/file1.csv",
  "path/to/your/file2.csv",
  "path/to/your/file3.csv",
]

#EWI: SPRKPY1026 => pyspark.sql.readwriter.DataFrameReader.csv has a workaround, see documentation for more info
df = session.read.csv(
  file_paths,
  schema=my_schema,
  encoding="UTF-8",
  header=True,
  sep=","
)
Copy

Correction recommandée

Dans cette section, nous expliquons comment configurer le paramètre path, le paramètre schema et certaines options pour les faire fonctionner dans Snowpark.

1. Paramètre path

Snowpark exige que le paramètre path soit un emplacement de zone de préparation. Pour contourner le problème, vous pouvez créer une zone de préparation temporaire et ajouter chaque fichier .csv à cette zone de préparation en utilisant le préfixe file://.

2. Paramètre schema

Snowpark ne permet pas de définir schema comme paramètre de la fonction csv. En guise de solution de contournement, vous pouvez utiliser la fonction snowflake.snowpark.DataFrameReader.schema.

3. Paramètres des options

Snowpark ne permet pas de définir les options supplémentaires comme paramètres de la fonction csv. Comme solution de contournement, vous pouvez utiliser la fonction Snowflake.snowpark.DataFrameReader.option pour spécifier ces paramètres en tant qu’options de DataFrameReader.

Note

Les options suivantes ne sont pas prises en charge par Snowpark :

  • columnNameOfCorruptRecord

  • emptyValue

  • enforceSchema

  • header

  • ignoreLeadingWhiteSpace

  • ignoreTrailingWhiteSpace

  • inferSchema

  • locale

  • maxCharsPerColumn

  • maxColumns

  • mode

  • multiLine

  • nanValue

  • negativeInf

  • nullValue

  • positiveInf

  • quoteAll

  • samplingRatio

  • timestampNTZFormat

  • unescapedQuoteHandling

Vous trouverez ci-dessous l’exemple complet de ce à quoi devrait ressembler le code d’entrée après avoir appliqué les suggestions mentionnées ci-dessus pour qu’il fonctionne dans Snowpark :

stage = f'{session.get_fully_qualified_current_schema()}.{_generate_prefix("TEMP_STAGE")}'
session.sql(f'CREATE TEMPORARY STAGE IF NOT EXISTS {stage}')

session.file.put(f"file:///path/to/your/file1.csv", f"@{stage}")
session.file.put(f"file:///path/to/your/file2.csv", f"@{stage}")
session.file.put(f"file:///path/to/your/file3.csv", f"@{stage}")

df = session.read.schema(my_schema).option("encoding", "UTF-8").option("sep", ",").csv(stage)
Copy

Recommandations supplémentaires

SPRKPY1077

Message : Le code intégré SQL ne peut pas être traité.

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte un code intégré SQL qui ne peut pas être converti en Snowpark.

Pour plus d’informations, consultez la section Code intégré SQL.

Scénario

Entrée

Dans cet exemple, le code SQL est intégré à une variable appelée requête qui est utilisée comme paramètre de la méthode Pyspark.sql.

query = f"SELECT * from myTable"
spark.sql(query)
Copy

Sortie

SMA détecte que le paramètre PySpark.sql est une variable et non un code SQL, de sorte que le message EWI SPRKPY1077 est ajouté à la ligne PySpark.sql.

query = f"SELECT * myTable"
#EWI: SPRKPY1077 => SQL embedded code cannot be processed.
spark.sql(query)
Copy

Recommandations supplémentaires

  • Pour la transformation de SQL, ce code doit être directement intégré en tant que paramètre de la méthode, uniquement sous forme de valeurs de chaîne et sans interpolation. Veuillez vérifier l’envoi de SQL à la fonction PySpark.SQL pour valider sa fonctionnalité sur Snowflake.

  • Pour plus d’assistance, vous pouvez nous envoyer un e-mail à sma-support@snowflake.com ou signaler un problème dans l’outil SMA.

SPRKPY1067

Message : La fonction pyspark.sql.functions.split a des paramètres qui ne sont pas pris en charge dans Snowpark.

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.functions.split avec plus de deux paramètres ou un modèle regex comme paramètre ; les deux cas ne sont pas pris en charge.

Scénarios

Scénario 1

Code d’entrée

Dans cet exemple, la fonction de fractionnement a plus de deux paramètres.

df.select(split(columnName, ",", 5))
Copy

Code de sortie

L’outil ajoute cet EWI au code de sortie pour vous indiquer que cette fonction n’est pas prise en charge lorsqu’elle comporte plus de deux paramètres.

#EWI: SPRKPY1067 => Snowpark does not support split functions with more than two parameters or containing regex pattern. See documentation for more info.
df.select(split(columnName, ",", 5))
Copy

Correction recommandée

Conservez la fonction de fractionnement avec seulement deux paramètres.

df.select(split(columnName, ","))
Copy
Scénario 2

Code d’entrée

Dans cet exemple, la fonction de fractionnement a pour paramètre un modèle regex.

df.select(split(columnName, "^([\d]+-[\d]+-[\d])"))
Copy

Code de sortie

L’outil ajoute cet EWI au code de sortie pour vous indiquer que cette fonction n’est pas prise en charge lorsqu’elle comporte un modèle regex comme paramètre.

#EWI: SPRKPY1067 => Snowpark does not support split functions with more than two parameters or containing regex pattern. See documentation for more info.
df.select(split(columnName, "^([\d]+-[\d]+-[\d])"))
Copy

Correction recommandée

La signature Spark de cette méthode functions.split(str: ColumnOrName, pattern: str, limit: int = - 1) ne correspond pas exactement à la méthode dans Snowpark functions.split(str: Union[Column, str], pattern: Union[Column, str]). Par conséquent, aucune correction recommandée n’existe pour le moment pour le scénario qui utilise une expression régulière.

Recommandations supplémentaires

SPRKPY1036

Avertissement

Ce code de problème est maintenant obsolète.

Message : pyspark.sql.column.Column.getField a une solution de contournement. Voir la documentation pour plus d’informations

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil SMA détecte une utilisation de la fonction pyspark.sql.column.Column.getField, qui dispose d’une solution de contournement.

Scénario

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de la fonction pyspark.sql.column.Column.getField qui génère cet EWI. Dans cet exemple, la fonction getField est utilisée pour extraire le nom de la colonne info.

df = spark.createDataFrame([(1, {"name": "John", "age": 30}), (2, {"name": "Jane", "age": 25})], ["id", "info"])
df_with_name = df.withColumn("name", col("info").getField("name"))
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1036 au code de sortie pour vous indiquer que cette fonction n’est pas directement prise en charge par Snowpark, mais qu’il existe une solution de contournement.

df = spark.createDataFrame([(1, {"name": "John", "age": 30}), (2, {"name": "Jane", "age": 25})], ["id", "info"])
#EWI: SPRKPY1036 => pyspark.sql.column.Column.getField has a workaround, see documentation for more info
df_with_name = df.withColumn("name", col("info").getField("name"))
Copy

Correction recommandée

Pour contourner ce problème, vous pouvez utiliser l”opérateur d’indexation de colonne de Snowpark avec le nom du champ comme index.

df = spark.createDataFrame([(1, {"name": "John", "age": 30}), (2, {"name": "Jane", "age": 25})], ["id", "info"])
df_with_name = df.withColumn("name", col("info")["name"])
Copy

Recommandations supplémentaires

SPRKPY1002

Message ** :** < element > n’est pas pris en charge, l’élément Spark n’est pas pris en charge.

Catégoriey ** :** Erreur de conversion.

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation d’un élément qui n’est pas pris en charge par Snowpark, et qui n’a pas son propre code d’erreur associé. Il s’agit du code d’erreur générique utilisé par SMA pour un élément non pris en charge.

Recommandations supplémentaires

  • Même si l’option ou l’élément du message n’est pas pris en charge, cela ne signifie pas qu’une solution ne peut être trouvée. Cela signifie seulement que l’outil lui-même ne peut pas trouver la solution.

  • Si vous avez rencontré un élément non pris en charge d’une bibliothèque pyspark.ml, envisagez une approche alternative. Il existe d’autres guides disponibles pour résoudre les problèmes liés à ML, comme celui de Snowflake.

  • Vérifiez que la syntaxe du code source est correcte. (Vous pouvez utiliser le fichier issues.csv pour déterminer où se produisent les erreurs de conversion) Si la syntaxe est correcte, signalez que vous avez rencontré une erreur de conversion sur un élément particulier en utilisant l’option Signaler un problème dans SMA. Incluez la ligne de code à l’origine de l’erreur dans la description lorsque vous déclarez ce problème.

  • Pour plus d’assistance, vous pouvez nous envoyer un e-mail à sma-support@snowflake.com ou signaler un problème dans l’outil SMA.

SPRKPY1053

Message : Une erreur s’est produite lors de l’extraction des fichiers dbc.

Catégorie : Avertissement

Description

Ce problème apparaît lorsqu’un fichier dbc ne peut pas être extrait. Cet avertissement peut être dû à une ou plusieurs des raisons suivantes : Trop lourd, inaccessible, en lecture seule, etc.

Recommandations supplémentaires

  • En guise de solution de contournement, vous pouvez vérifier la taille du fichier s’il est trop lourd pour être traité. Analysez également si l’outil peut y accéder afin d’éviter tout problème d’accès.

  • Pour plus d’assistance, vous pouvez nous envoyer un e-mail à l’adresse suivante : snowconvert-info@snowflake.com. Si vous avez un contrat de support avec Snowflake, contactez votre ingénieur commercial, qui pourra répondre à vos besoins en matière d’assistance.

SPRKPY1080

Message : La valeur de SparkContext est remplacée par la variable “session”.

Catégorie : Avertissement

Description

Le contexte de Spark est stocké dans une variable appelée session qui crée une session Snowpark.

Scénario

Entrée

Cet extrait décrit un SparkContext.

## Input Code
from pyspark import SparkContext
from pyspark.sql import SparkSession

def example1():

    sc = SparkContext("local[*]", "TestApp")

    sc.setLogLevel("ALL")
    sc.setLogLevel("DEBUG")
Copy

Sortie

Dans ce code de sortie, SMA a remplacé PySpark.SparkContext par SparkSession. Notez que l’outil SMA ajoute également un modèle pour remplacer la connexion dans le fichier « connection.json » et charge ensuite cette configuration dans la variable connection_parameter.

## Output Code
import logging
import sys
import json
from snowflake.snowpark import Session
from snowflake.snowpark import Session

def example1():
    jsonFile = open("connection.json")
    connection_parameter = json.load(jsonFile)
    jsonFile.close()
    #EWI: SPRKPY1080 => The value of SparkContext is replaced with 'session' variable.
    sc = Session.builder.configs(connection_parameter).getOrCreate()
    sc.update_query_tag({"origin":"sf_sit","name":"sma","version":{"major":0,"minor":0,"patch":0},"attributes":{"language":"Python"}})
    logging.basicConfig(stream = sys.stdout, level = logging.NOTSET)
    logging.basicConfig(stream = sys.stdout, level = logging.DEBUG)
Copy

Correction recommandée

Le fichier de configuration « connection.json » doit être mis à jour avec les informations de connexion requises :

{
  "user": "my_user",
  "password": "my_password",
  "account": "my_account",
  "role": "my_role",
  "warehouse": "my_warehouse",
  "database": "my_database",
  "schema": "my_schema"
}
Copy

Recommandations supplémentaires

SPRKPY1073

Message : pyspark.sql.functions.udf sans paramètre ou paramètre de type retour n’est pas pris en charge.

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.functions.udf en tant que fonction ou décorateur et n’est pas pris en charge dans deux cas spécifiques, lorsqu’il n’a pas de paramètre ou de paramètre de type retour.

Scénarios

Scénario 1

Entrée

Dans Pyspark, vous pouvez créer une fonction définie par l’utilisateur sans paramètres de type d’entrée ou de retour :

from pyspark.sql import SparkSession, DataFrameStatFunctions
from pyspark.sql.functions import col, udf

spark = SparkSession.builder.getOrCreate()
data = [['Q1', 'Test 1'],
        ['Q2', 'Test 2'],
        ['Q3', 'Test 1'],
        ['Q4', 'Test 1']]

columns = ['Quadrant', 'Value']
df = spark.createDataFrame(data, columns)

my_udf = udf(lambda s: len(s))
df.withColumn('Len Value' ,my_udf(col('Value')) ).show()
Copy

Sortie

Snowpark exige les types d’entrée et de retour pour la fonction Udf. En effet, ils ne sont pas fournis et SMA ne peut pas définir ces paramètres.

from snowflake.snowpark import Session, DataFrameStatFunctions
from snowflake.snowpark.functions import col, udf

spark = Session.builder.getOrCreate()
spark.update_query_tag({"origin":"sf_sit","name":"sma","version":{"major":0,"minor":0,"patch":0},"attributes":{"language":"Python"}})
data = [['Q1', 'Test 1'],
        ['Q2', 'Test 2'],
        ['Q3', 'Test 1'],
        ['Q4', 'Test 1']]

columns = ['Quadrant', 'Value']
df = spark.createDataFrame(data, columns)
#EWI: SPRKPY1073 => pyspark.sql.functions.udf function without the return type parameter is not supported. See documentation for more info.
my_udf = udf(lambda s: len(s))

df.withColumn('Len Value' ,my_udf(col('Value')) ).show()
Copy

Correction recommandée

Pour corriger ce scénario, il est nécessaire d’ajouter l’importation des types de retour de l’entrée et de la sortie, puis les paramètres du type de retour et des types d’entrée[] à la fonction udf _my_udf.

from snowflake.snowpark import Session, DataFrameStatFunctions
from snowflake.snowpark.functions import col, udf
from snowflake.snowpark.types import IntegerType, StringType

spark = Session.builder.getOrCreate()
spark.update_query_tag({"origin":"sf_sit","name":"sma","version":{"major":0,"minor":0,"patch":0},"attributes":{"language":"Python"}})
data = [['Q1', 'Test 1'],
        ['Q2', 'Test 2'],
        ['Q3', 'Test 1'],
        ['Q4', 'Test 1']]

columns = ['Quadrant', 'Value']
df = spark.createDataFrame(data, columns)

my_udf = udf(lambda s: len(s), return_type=IntegerType(), input_types=[StringType()])

df.with_column("result", my_udf(df.Value)).show()
Copy
Scénario 2

Dans PySpark, vous pouvez utiliser un décorateur @udf sans paramètres.

Entrée

from pyspark.sql.functions import col, udf

spark = SparkSession.builder.getOrCreate()
data = [['Q1', 'Test 1'],
        ['Q2', 'Test 2'],
        ['Q3', 'Test 1'],
        ['Q4', 'Test 1']]

columns = ['Quadrant', 'Value']
df = spark.createDataFrame(data, columns)

@udf()
def my_udf(str):
    return len(str)


df.withColumn('Len Value' ,my_udf(col('Value')) ).show()
Copy

Sortie

Dans Snowpark, tous les paramètres d’un décorateur udf sont requis.

from snowflake.snowpark.functions import col, udf

spark = Session.builder.getOrCreate()
spark.update_query_tag({"origin":"sf_sit","name":"sma","version":{"major":0,"minor":0,"patch":0},"attributes":{"language":"Python"}})
data = [['Q1', 'Test 1'],
        ['Q2', 'Test 2'],
        ['Q3', 'Test 1'],
        ['Q4', 'Test 1']]

columns = ['Quadrant', 'Value']
df = spark.createDataFrame(data, columns)

#EWI: SPRKPY1073 => pyspark.sql.functions.udf decorator without parameters is not supported. See documentation for more info.

@udf()
def my_udf(str):
    return len(str)

df.withColumn('Len Value' ,my_udf(col('Value')) ).show()
Copy

Correction recommandée

Pour corriger ce scénario, il est nécessaire d’ajouter l’importation des types de retour de l’entrée et de la sortie, puis les paramètres du type de retour et des types d’entrée[] au décorateur udf @udf.

from snowflake.snowpark.functions import col, udf
from snowflake.snowpark.types import IntegerType, StringType

spark = Session.builder.getOrCreate()
spark.update_query_tag({"origin":"sf_sit","name":"sma","version":{"major":0,"minor":0,"patch":0},"attributes":{"language":"Python"}})
data = [['Q1', 'Test 1'],
        ['Q2', 'Test 2'],
        ['Q3', 'Test 1'],
        ['Q4', 'Test 1']]

columns = ['Quadrant', 'Value']
df = spark.createDataFrame(data, columns)

@udf(return_type=IntegerType(), input_types=[StringType()])
def my_udf(str):
    return len(str)

df.withColumn('Len Value' ,my_udf(col('Value')) ).show()
Copy

Recommandations supplémentaires

SPRKPY1022

Message : pyspark.sql.functions.log10 a une solution de contournement. Voir la documentation pour plus d’informations

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil SMA détecte une utilisation de la fonction pyspark.sql.functions.log10, qui dispose d’une solution de contournement.

Scénario

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de la fonction pyspark.sql.functions.log10 qui génère cet EWI. Dans cet exemple, la fonction log10 est utilisée pour calculer le logarithme base-10 de la colonne value.

df = spark.createDataFrame([(1,), (10,), (100,), (1000,), (10000,)], ["value"])
df_with_log10 = df.withColumn("log10_value", log10(df["value"]))
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1022 au code de sortie pour vous indiquer que cette fonction n’est pas directement prise en charge par Snowpark, mais qu’il existe une solution de contournement.

df = spark.createDataFrame([(1,), (10,), (100,), (1000,), (10000,)], ["value"])
#EWI: SPRKPY1022 => pyspark.sql.functions.log10 has a workaround, see documentation for more info
df_with_log10 = df.withColumn("log10_value", log10(df["value"]))
Copy

Correction recommandée

Pour contourner le problème, vous pouvez utiliser la fonction Snowflake.snowpark.functions.log en transmettant la valeur littérale 10 comme base.

df = spark.createDataFrame([(1,), (10,), (100,), (1000,), (10000,)], ["value"])
df_with_log10 = df.withColumn("log10_value", log(10, df["value"]))
Copy

Recommandations supplémentaires

SPRKPY1016

Avertissement

Ce code de problème est obsolète depuis Spark Conversion Core Version 0.11.7

Message : pyspark.sql.functions.collect_set a une solution de contournement

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.functions.collect_set qui dispose d’une solution de contournement.

Scénario

Entrée

L’utilisation de collect set permet d’obtenir les éléments de _colname sans doublons :

col = collect_set(colName)
Copy

Sortie

SMA renvoie l’EWI SPRKPY1016 sur la ligne où collect_set est utilisé, ce qui vous permet d’identifier l’endroit à corriger.

#EWI: SPRKPY1016 => pyspark.sql.functions.collect_set has a workaround, see documentation for more info
col = collect_set(colName)
Copy

Correction recommandée

Utilisez la fonction array_agg et ajoutez un deuxième argument avec la valeur True.

col = array_agg(col, True)
Copy

Recommandation supplémentaire

SPRKPY1047

Avertissement

Ce code de problème est obsolète depuis Spark Conversion Core Version 4.6.0

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.context.SparkContext.setLogLevel qui dispose d’une solution de contournement.

Scénario

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de la méthode setLogLevel.

sparkSession.sparkContext.setLogLevel("WARN")
Copy

Sortie

L’outil ajoute l’EWI SPRKPY1047 indiquant qu’une solution de contournement peut être mise en œuvre.

#EWI: SPRKPY1047 => pyspark.context.SparkContext.setLogLevel has a workaround, see documentation for more info
sparkSession.sparkContext.setLogLevel("WARN")
Copy

Correction recommandée

Remplacez l’utilisation de la fonction setLogLevel par logging.basicConfig qui fournit un ensemble de fonctions de commodité pour une utilisation simple de la journalisation. Pour l’utiliser, nous devons importer deux modules, « logging » et « sys », et la constante « level » doit être remplacée par « Level equivalent table » :

import logging
import sys
logging.basicConfig(stream=sys.stdout, level=logging.WARNING)
Copy
  • Table d’équivalence des niveaux

Paramètre source du niveau

Paramètre cibl du niveaue

« ALL »

N’a pas d’équivalent

« DEBUG »

logging.DEBUG

« ERROR »

logging.ERROR

« FATAL »

logging.CRITICAL

« INFO »

logging.INFO

« OFF »

logging.NOTSET

« TRACE »

N’a pas d’équivalent

« WARN »

logging.WARNING

Recommandations supplémentaires

SPRKPY1057

Avertissement

Ce code de problème est obsolète depuis Spark Conversion Core Version 4.8.0

Message : L’argument de l’option du dataframe PySpark contient une valeur qui n’est pas un littéral. Il ne peut donc pas être évalué.

Catégorie : Avertissement

Description

Ce code de problème est obsolète. Si vous utilisez une version plus ancienne, veuillez la mettre à jour.

Recommandations supplémentaires

SPRKPY1006

Avertissement

Ce code de problème est obsolète depuis Spark Conversion Core Version 4.8.0

Messagee ** :** pyspark.context.SparkContext n’est pas nécessaire

Catégoriey ** :** Avertissement.

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.context.SparkContext qui n’est pas requis dans Snowflake.

Scénario

Entrée

Dans cet exemple, il y a deux contextes pour créer une connexion à un cluster Spark.

from pyspark import SparkContext

sql_context1 = SparkContext(my_sc1)
sql_context2 = SparkContext(sparkContext=my_sc2)
Copy

Sortie

Étant donné qu’il n’y a pas de cluster dans Snowflake, le contexte n’est pas nécessaire. Notez que les variables my_sc1 et my_sc2 qui contiennent les propriétés Spark peuvent ne pas être nécessaires ou devront être adaptées pour corriger le code.

from snowflake.snowpark import Session
#EWI: SPRKPY1006 => pyspark.sql.context.SparkContext is not required
sql_context1 = my_sc1
#EWI: SPRKPY1006 => pyspark.sql.context.SparkContext is not required

sql_context2 = my_sc2
Copy

Recommandations supplémentaires

  • Il s’agit de la suppression d’un paramètre inutile et de l’insertion d’un commentaire d’avertissement. L’utilisateur ne doit effectuer aucune action.

  • Pour plus d’assistance, vous pouvez nous envoyer un e-mail à sma-support@snowflake.com ou signaler un problème dans l’outil SMA.

SPRKPY1032

Message : l’élément Spark n’est pas défini.

Catégorie : Erreur de conversion

Description

Ce problème apparaît lorsque l’outil SMA n’a pas pu déterminer un statut de mappage approprié pour l’élément donné. Cela signifie que SMA ne sait pas encore si cet élément est pris en charge ou non par Snowpark. Veuillez noter qu’il s’agit d’un code d’erreur générique utilisé par SMA pour tout élément non défini.

Scénario

Entrée

Vous trouverez ci-dessous un exemple de fonction pour laquelle SMA n’a pas pu déterminer un statut de mappage approprié. Dans ce cas, vous devez supposer que not_defined_function() est une fonction PySpark valide et que le code s’exécute.

sc.parallelize(["a", "b", "c", "d", "e"], 3).not_defined_function().collect()
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1032 au code de sortie pour vous indiquer que cet élément n’est pas défini.

#EWI: SPRKPY1032 => pyspark.rdd.RDD.not_defined_function is not defined
sc.parallelize(["a", "b", "c", "d", "e"], 3).not_defined_function().collect()
Copy

Correction recommandée

Pour tenter d’identifier le problème, vous pouvez effectuer les validations suivantes :

  • Vérifiez que la syntaxe du code source est correcte et qu’il est correctement orthographié.

  • Vérifiez que vous utilisez une version de PySpark prise en charge par SMA. Pour savoir quelle version de PySpark est prise en charge par SMA au moment de l’exécution de SMA, vous pouvez consulter la première page du fichier DetailedReport.docx.

S’il s’agit d’un élément PySpark valide, veuillez signaler que vous avez rencontré une erreur de conversion sur cet élément particulier en utilisant l’option Signaler un problème de l’outil SMA et incluez toute information supplémentaire que vous jugez utile.

Veuillez noter que si un élément n’est pas défini, cela ne signifie pas qu’il n’est pas pris en charge par Snowpark. Vous devez consulter la documentation de Snowpark pour vérifier qu’un élément équivalent existe.

Recommandations supplémentaires

SPRKPY1063

Message : pyspark.sql.pandas.functions.pandas_udf a une solution de contournement.

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.pandas.functions.pandas_udf qui dispose d’une solution de contournement.

Scénario

Entrée

La fonction pandas_udf est utilisée pour créer une fonction définie par l’utilisateur qui travaille avec de grandes quantités de données.

@pandas_udf(schema, PandasUDFType.GROUPED_MAP)
def modify_df(pdf):
    return pd.DataFrame({'result': pdf['col1'] + pdf['col2'] + 1})
df = spark.createDataFrame([(1, 2), (3, 4), (1, 1)], ["col1", "col2"])
new_df = df.groupby().apply(modify_df)
Copy

Sortie

L’outil SMA ajoute un message EWI indiquant que la fonction pandas_udf a une solution de contournement.

#EWI: SPRKPY1062 => pyspark.sql.pandas.functions.pandas_udf has a workaround, see documentation for more info
@pandas_udf(schema, PandasUDFType.GROUPED_MAP)

def modify_df(pdf):
    return pd.DataFrame({'result': pdf['col1'] + pdf['col2'] + 1})

df = spark.createDataFrame([(1, 2), (3, 4), (1, 1)], ["col1", "col2"])

new_df = df.groupby().apply(modify_df)
Copy

Correction recommandée

Spécifiez explicitement les types de paramètres sous la forme d’un nouveau paramètre input_types, et supprimez le paramètre functionType le cas échéant. La fonction créée doit être appelée à l’intérieur d’une instruction de sélection.

@pandas_udf(
    return_type = schema,
    input_types = [PandasDataFrameType([IntegerType(), IntegerType()])]
)

def modify_df(pdf):
    return pd.DataFrame({'result': pdf['col1'] + pdf['col2'] + 1})

df = spark.createDataFrame([(1, 2), (3, 4), (1, 1)], ["col1", "col2"])

new_df = df.groupby().apply(modify_df) # You must modify function call to be a select and not an apply
Copy

Recommandations supplémentaires

SPRKPY1078

Message : L’argument de la fonction pyspark.context.SparkContext.setLogLevel n’est pas une valeur littérale et n’a donc pas pu être évalué.

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil SMA détecte l’utilisation de la fonction pyspark.context.SparkContext.setLogLevel avec un argument qui n’est pas une valeur littérale, par exemple, lorsque l’argument est une variable.

L’outil SMA effectue une analyse statique de votre code source et il n’est donc pas possible d’évaluer le contenu de cet argument et de déterminer un équivalent dans Snowpark.

Scénario

Entrée

Dans cet exemple, le niveau de journalisation est défini dans la variable my_log_level, puis my_log_level est utilisé comme paramètre par la méthode setLogLevel.

my_log_level = "WARN"
sparkSession.sparkContext.setLogLevel(my_log_level)
Copy

Sortie

SMA n’est pas en mesure d’évaluer l’argument du paramètre du niveau de journalisation, de sorte que l’EWI SPRKPY1078 est ajouté par-dessus la ligne de la journalisation transformée :

my_log_level = "WARN"
#EWI: SPRKPY1078 => my_log_level is not a literal value and therefore could not be evaluated. Make sure the value of my_log_level is a valid level in Snowpark. Valid log levels are: logging.CRITICAL, logging.DEBUG, logging.ERROR, logging.INFO, logging.NOTSET, logging.WARNING
logging.basicConfig(stream = sys.stdout, level = my_log_level)
Copy

Correction recommandée

Même si l’outil SMA n’a pas pu évaluer l’argument, il transformera la fonction pyspark.context.SparkContext.setLogLevel en son équivalent Snowpark. Veuillez vous assurer que la valeur de l’argument level dans le code de sortie généré est un niveau de journalisation valide et équivalent dans Snowpark selon la table ci-dessous :

Niveau de journalisation PySpark

Équivalent Snowpark du niveau de journalisation

ALL

logging.NOTSET

DEBUG

logging.DEBUG

ERROR

logging.ERROR

FATAL

logging.CRITICAL

INFO

logging.INFO

OFF

logging.WARNING

TRACE

logging.NOTSET

WARN

logging.WARNING

La correction recommandée se présente donc comme suit :

my_log_level = logging.WARNING
logging.basicConfig(stream = sys.stdout, level = my_log_level)
Copy

Recommandations supplémentaires

SPRKPY1029

Message : Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.readwriter.DataFrameReader.parquet. Cette fonction est prise en charge, mais certaines différences entre Snowpark et Spark API peuvent nécessiter quelques modifications manuelles.

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil SMA détecte une utilisation de la fonction pyspark.sql.readwriter.DataFrameReader.parquet. Cette fonction est prise en charge par Snowpark, mais il existe quelques différences qui nécessiteraient des modifications manuelles.

Scénario

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de la fonction pyspark.sql.readwriter.DataFrameReader.parquet qui génère cet EWI.

file_paths = [
  "path/to/your/file1.parquet",
  "path/to/your/file2.parquet",
  "path/to/your/file3.parquet",
]

df = session.read.parquet(
  *file_paths,
  mergeSchema="true",
  pathGlobFilter="*file*",
  recursiveFileLookup="true",
  modifiedBefore="2024-12-31T00:00:00",
  modifiedAfter="2023-12-31T00:00:00"
)
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1029 au code de sortie pour vous indiquer que cette fonction n’est pas prise en charge par Snowpark, mais que certains ajustements manuels sont nécessaires. Veuillez noter que les options prises en charge par Snowpark sont transformées en appels de fonction option et que celles qui ne sont pas prises en charge sont supprimées. Ceci est expliqué plus en détail dans les sections suivantes.

file_paths = [
  "path/to/your/file1.parquet",
  "path/to/your/file2.parquet",
  "path/to/your/file3.parquet"
]

#EWI: SPRKPY1076 => Some of the included parameters are not supported in the parquet function, the supported ones will be added into a option method.
#EWI: SPRKPY1029 => This issue appears when the tool detects the usage of pyspark.sql.readwriter.DataFrameReader.parquet. This function is supported, but some of the differences between Snowpark and the Spark API might require making some manual changes.
df = session.read.option("PATTERN", "*file*").parquet(
  *file_paths
)
Copy

Correction recommandée

Dans cette section, nous expliquons comment configurer les paramètres paths et options pour les faire fonctionner dans Snowpark.

1. Paramètre path

Dans Spark, ce paramètre peut être un emplacement local ou Cloud. Snowpark n’accepte que les emplacements Cloud utilisant une zone de préparation Snowflake. Vous pouvez donc créer une zone de préparation interne et y ajouter chaque fichier en utilisant le préfixe file://.

2. Paramètre des options

Snowpark ne permet pas de définir les différentes options comme paramètres de la fonction parquet. Pour contourner le problème, vous pouvez utiliser les fonctions option ou options pour spécifier ces paramètres en tant qu’options supplémentaires de DataFrameReader.

Veuillez noter que les options Snowpark ne sont pas exactement les mêmes que les options PySpark et que des modifications manuelles peuvent donc être nécessaires. Vous trouverez ci-dessous une explication plus détaillée de la configuration des options PySpark les plus courantes dans Snowpark.

2.1 Option mergeSchema

Parquet prend en charge l’évolution des schémas, ce qui permet aux utilisateurs de commencer avec un schéma simple et d’ajouter progressivement des colonnes en fonction des besoins. Il peut en résulter plusieurs fichiers Parquet avec des schémas différents mais compatibles. Dans Snowflake, grâce aux fonctionnalités d”infer_schema, cette action n’est pas nécessaire. L’option mergeSchema peut donc être supprimée.

2.2 Option pathGlobFilter

Si vous souhaitez ne charger qu’un sous-ensemble de fichiers de la zone de préparation, vous pouvez utiliser l’option pattern pour spécifier une expression régulière correspondant aux fichiers que vous souhaitez charger. L’outil SMA automatise déjà cette opération, comme vous pouvez le voir dans la sortie de ce scénario.

2.3 Option recursiveFileLookupstr

Cette option n’est pas prise en charge par Snowpark. La meilleure recommandation est d’utiliser une expression régulière comme avec l’option pathGlobFilter pour obtenir quelque chose de similaire.

2.4 Option modifiedBefore / modifiedAfter

Vous pouvez obtenir le même résultat dans Snowflake en utilisant les colonnes metadata.

Note

Les options suivantes ne sont pas prises en charge par Snowpark :

  • compression

  • datetimeRebaseMode

  • int96RebaseMode

  • mergeSchema

Vous trouverez ci-dessous l’exemple complet de la façon dont le code d’entrée doit être transformé pour qu’il fonctionne dans Snowpark :

from snowflake.snowpark.column import METADATA_FILE_LAST_MODIFIED, METADATA_FILENAME

temp_stage = f'{session.get_fully_qualified_current_schema()}.{_generate_prefix("TEMP_STAGE")}'
session.sql(f'CREATE TEMPORARY STAGE IF NOT EXISTS {temp_stage}')

session.file.put(f"file:///path/to/your/file1.parquet", f"@{temp_stage}")
session.file.put(f"file:///path/to/your/file2.parquet", f"@{temp_stage}")
session.file.put(f"file:///path/to/your/file3.parquet", f"@{temp_stage}")

df = session.read \
  .option("PATTERN", ".*file.*") \
  .with_metadata(METADATA_FILENAME, METADATA_FILE_LAST_MODIFIED) \
  .parquet(temp_stage) \
  .where(METADATA_FILE_LAST_MODIFIED < '2024-12-31T00:00:00') \
  .where(METADATA_FILE_LAST_MODIFIED > '2023-12-31T00:00:00')
Copy

Recommandations supplémentaires

SPRKPY1039

Avertissement

Ce code de problème est maintenant obsolète.

Message : pyspark.sql.column.Column.getItem a une solution de contournement. Voir la documentation pour plus d’informations

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil SMA détecte une utilisation de la fonction pyspark.sql.column.Column.getItem, qui dispose d’une solution de contournement.

Scénario

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de la fonction pyspark.sql.column.Column.getItem qui génère cet EWI. Dans cet exemple, la fonction getItem est utilisée pour obtenir un élément par position et par clé.

df = spark.createDataFrame([(1, ["apple", "banana", "orange"]), (2, ["carrot", "avocado", "banana"])], ["id", "fruits"])
df.withColumn("first_fruit", col("fruits").getItem(0))

df = spark.createDataFrame([(1, {"apple": 10, "banana": 20}), (2, {"carrot": 15, "grape": 25}), (3, {"pear": 30, "apple": 35})], ["id", "fruit_quantities"])
df.withColumn("apple_quantity", col("fruit_quantities").getItem("apple"))
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1039 au code de sortie pour vous indiquer que cette fonction n’est pas directement prise en charge par Snowpark, mais qu’il existe une solution de contournement.

df = spark.createDataFrame([(1, ["apple", "banana", "orange"]), (2, ["carrot", "avocado", "banana"])], ["id", "fruits"])
#EWI: SPRKPY1039 => pyspark.sql.column.Column.getItem has a workaround, see documentation for more info
df.withColumn("first_fruit", col("fruits").getItem(0))

df = spark.createDataFrame([(1, {"apple": 10, "banana": 20}), (2, {"carrot": 15, "grape": 25}), (3, {"pear": 30, "apple": 35})], ["id", "fruit_quantities"])
#EWI: SPRKPY1039 => pyspark.sql.column.Column.getItem has a workaround, see documentation for more info
df.withColumn("apple_quantity", col("fruit_quantities").getItem("apple"))
Copy

Correction recommandée

Pour contourner ce problème, vous pouvez utiliser l”opérateur d’indexation de colonne de Snowpark avec le nom ou la position du champ comme index.

df = spark.createDataFrame([(1, ["apple", "banana", "orange"]), (2, ["carrot", "avocado", "banana"])], ["id", "fruits"])
df.withColumn("first_fruit", col("fruits")[0])

df = spark.createDataFrame([(1, {"apple": 10, "banana": 20}), (2, {"carrot": 15, "grape": 25}), (3, {"pear": 30, "apple": 35})], ["id", "fruit_quantities"])
df.withColumn("apple_quantity", col("fruit_quantities")["apple"])
Copy

Recommandations supplémentaires

SPRKPY1068

Message : toPandas contient des colonnes de type ArrayType qui n’est pas pris en charge et qui dispose d’une solution de contournement.

Catégorie : Avertissement

Description

pyspark.sql.DataFrame.toPandas ne fonctionne pas correctement en cas de colonnes de type ArrayType. Dans ce cas, la solution consiste à convertir ces colonnes en un dictionnaire Python à l’aide de la méthode json.loads.

Scénario

Entrée

ToPandas renvoie les données du DataFrame d’origine sous la forme d’un DataFrame Pandas.

sparkDF = spark.createDataFrame([
Row(a=1, b=2., c='string1', d=date(2000, 1, 1), e=datetime(2000, 1, 1, 12, 0)),
Row(a=2, b=3., c='string2', d=date(2000, 2, 1), e=datetime(2000, 1, 2, 12, 0))
])

pandasDF = sparkDF.toPandas()
Copy

Sortie

L’outil ajoute cet EWI pour vous indiquer que toPandas n’est pas pris en charge en cas de colonnes de type ArrayType, mais qu’il existe une solution de contournement.

sparkDF = spark.createDataFrame([
Row(a=1, b=2., c='string1', d=date(2000, 1, 1), e=datetime(2000, 1, 1, 12, 0)),
Row(a=2, b=3., c='string2', d=date(2000, 2, 1), e=datetime(2000, 1, 2, 12, 0))
])
#EWI: SPRKPY1068 => toPandas doesn't work properly If there are columns of type ArrayType. The workaround for these cases is converting those columns into a Python Dictionary by using json.loads method. example: df[colName] = json.loads(df[colName]).
pandasDF = sparkDF.toPandas()
Copy

Correction recommandée

pandas_df = sparkDF.toPandas()

## check/convert all resulting fields from calling toPandas when they are of
## type ArrayType,
## they will be reasigned by converting them into a Python Dictionary
## using json.loads method​

for field in pandas_df.schema.fields:
    if isinstance(field.datatype, ArrayType):
        pandas_df[field.name] = pandas_df[field.name].apply(lambda x: json.loads(x) if x is not None else x)
Copy

Recommandations supplémentaires

SPRKPY1048

Avertissement

Ce code de problème est obsolète depuis Spark Conversion Core Version 2.4.0

Message : pyspark.sql.session.SparkSession.conf a une solution de contournement

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.session.SparkSession.conf qui dispose d’une solution de contournement.

Scénario

Entrée

Vous trouverez ci-dessous un exemple de définition d’une configuration dans la propriété conf.

spark.conf.set("spark.sql.crossJoin.enabled", "true")
Copy

Sortie

L’outil ajoute l’EWI SPRKPY1048 indiquant qu’une solution de contournement peut être mise en œuvre.

#EWI: SPRKPY1048 => pyspark.sql.session.SparkSession.conf has a workaround, see documentation for more info
spark.conf.set("spark.sql.crossJoin.enabled", "true")
Copy

Correction recommandée

SparkSession.conf est utilisé pour transférer certains paramètres spécifiques utilisés uniquement par Pyspark et ne s’applique pas à Snowpark. Vous pouvez supprimer ou commenter le code

#spark.conf.set("spark.sql.crossJoin.enabled", "true")
Copy

Recommandations supplémentaires

SPRKPY1019

Avertissement

Ce code de problème est obsolète depuis Spark Conversion Core Version 4.8.0

Message : pyspark.sql.functions.datediff a une solution de contournement

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.functions.datediff qui dispose d’une solution de contournement.

Scénario

Entrée

Dans cet exemple, nous utilisons datediff pour calculer la différence de jour entre “today” et d’autres dates.

contacts = (contacts
            #days since last event
            .withColumn('daysSinceLastEvent', datediff(lit(today),'lastEvent'))
            #days since deployment
            .withColumn('daysSinceLastDeployment', datediff(lit(today),'lastDeploymentEnd'))
            #days since online training
            .withColumn('daysSinceLastTraining', datediff(lit(today),'lastTraining'))
            #days since last RC login
            .withColumn('daysSinceLastRollCallLogin', datediff(lit(today),'adx_identity_lastsuccessfullogin'))
            #days since last EMS login
            .withColumn('daysSinceLastEMSLogin', datediff(lit(today),'vms_lastuserlogin'))
           )
Copy

Sortie

SMA renvoie l’EWI SPRKPY1019 sur la ligne où datediff est utilisé, ce qui vous permet d’identifier l’endroit à corriger.

from pyspark.sql.functions import datediff
#EWI: SPRKPY1019 => pyspark.sql.functions.datediff has a workaround, see documentation for more info
contacts = (contacts
            #days since last event
            .withColumn('daysSinceLastEvent', datediff(lit(today),'lastEvent'))
            #days since deployment
            .withColumn('daysSinceLastDeployment', datediff(lit(today),'lastDeploymentEnd'))
            #days since online training
            .withColumn('daysSinceLastTraining', datediff(lit(today),'lastTraining'))
            #days since last RC login
            .withColumn('daysSinceLastRollCallLogin', datediff(lit(today),'adx_identity_lastsuccessfullogin'))
            #days since last EMS login
            .withColumn('daysSinceLastEMSLogin', datediff(lit(today),'vms_lastuserlogin'))
           )
Copy

L’outil SMA convertit pyspark.sql.functions.datediff en snowflake.snowpark.functions.daydiff, ce qui calcule également la différence en jours entre deux dates.

Correction recommandée

datediff(part: string ,end: ColumnOrName, start: ColumnOrName)

Action : Importez Snowflake.snowpark.functions, qui contient une implémentation de la fonction datediff qui nécessite un paramètre supplémentaire pour la partie date-heure et permet une plus grande polyvalence dans le calcul des différences entre les dates.

from snowflake.snowpark import Session
from snowflake.snowpark.functions import datediff
contacts = (contacts
            #days since last event
            .withColumn('daysSinceLastEvent', datediff('day', lit(today),'lastEvent'))
            #days since deployment
            .withColumn('daysSinceLastDeployment', datediff('day',lit(today),'lastDeploymentEnd'))
            #days since online training
            .withColumn('daysSinceLastTraining', datediff('day', lit(today),'lastTraining'))
            #days since last RC login
            .withColumn('daysSinceLastRollCallLogin', datediff('day', lit(today),'adx_identity_lastsuccessfullogin'))
            #days since last EMS login
            .withColumn('daysSinceLastEMSLogin', datediff('day', lit(today),'vms_lastuserlogin'))
           )
Copy

Recommandation

SPRKPY1009

Message ** :** pyspark.sql.dataframe.DataFrame.approxQuantile a une solution de contournement

Catégoriey ** :** Avertissement.

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.dataframe.DataFrame.approxQuantile qui dispose d’une solution de contournement.

Scénario

Entrée

Il est important de comprendre que Pyspark utilise deux fonctions approxQuantile différentes, nous utilisons ici la version DataFrame approxQuantile.

from pyspark.sql import SparkSession
spark = SparkSession.builder.getOrCreate()
data = [['Sun', 10],
        ['Mon', 64],
        ['Thr', 12],
        ['Wen', 15],
        ['Thu', 68],
        ['Fri', 14],
        ['Sat', 13]]

columns = ['Day', 'Ammount']
df = spark.createDataFrame(data, columns)
df.approxQuantile('Ammount', [0.25, 0.5, 0.75], 0)
Copy

Sortie

SMA renvoie l’EWI SPRKPY1009 sur la ligne où approxQuantile est utilisé, ce qui vous permet d’identifier l’endroit à corriger.

from snowflake.snowpark import Session
spark = Session.builder.getOrCreate()
spark.update_query_tag({"origin":"sf_sit","name":"sma","version":{"major":0,"minor":0,"patch":0},"attributes":{"language":"Python"}})
data = [['Sun', 10],
        ['Mon', 64],
        ['Thr', 12],
        ['Wen', 15],
        ['Thu', 68],
        ['Fri', 14],
        ['Sat', 13]]

columns = ['Day', 'Ammount']
df = spark.createDataFrame(data, columns)
#EWI: SPRKPY1009 => pyspark.sql.dataframe.DataFrame.approxQuantile has a workaround, see documentation for more info
df.approxQuantile('Ammount', [0.25, 0.5, 0.75], 0)
Copy

Correction recommandée

Utilisez la méthode approxQuantile Snowpark. Certains paramètres ne correspondent pas et nécessitent donc des corrections manuelles. Pour l’exemple du code de sortie, la correction recommandée pourrait être la suivante :

from snowflake.snowpark import Session
...
df = spark.createDataFrame(data, columns)

df.stat.approx_quantile('Ammount', [0.25, 0.5, 0.75])
Copy

Le paramètre d’erreur relatif à pyspark.sql.dataframe.DataFrame.approxQuantile n’existe pas dans SnowPark.

Recommandations supplémentaires

SPRKPY1058

Message : La clé spécifique à la plateforme < méthode > avec < clé > n’est pas prise en charge.

Catégorie : ConversionError

Description

Les méthodes get et set de pyspark.sql.conf.RuntimeConfig ne sont pas prises en charge avec une clé spécifique à la plateforme.

Scénarios

Toutes les utilisations des méthodes get ou set n’auront pas forcément un EWI dans le code de sortie. Cet EWI apparaît lorsque l’outil détecte l’utilisation de ces méthodes avec une clé spécifique à la plateforme qui n’est pas prise en charge.

Scénario 1

Entrée

Vous trouverez ci-dessous un exemple des méthodes get ou set avec les clés prises en charge dans Snowpark.

session.conf.set("use_constant_subquery_alias", False)
spark.conf.set("sql_simplifier_enabled", True)

session.conf.get("use_constant_subquery_alias")
session.conf.get("use_constant_subquery_alias")
Copy

Sortie

Étant donné que les clés sont prises en charge dans Snowpark, l’outil n’ajoute pas l’EWI au code de sortie.

session.conf.set("use_constant_subquery_alias", True)
session.conf.set("sql_simplifier_enabled", False)

session.conf.get("use_constant_subquery_alias")
session.conf.get("sql_simplifier_enabled")
Copy

Correction recommandée

Il n’y a pas de correction recommandée pour ce scénario.

Scénario 2

Entrée

Vous trouverez ci-dessous un exemple d’utilisation des clés non prises en charge.

data =
    [
      ("John", 30, "New York"),
      ("Jane", 25, "San Francisco")
    ]

session.conf.set("spark.sql.shuffle.partitions", "50")
spark.conf.set("spark.yarn.am.memory", "1g")

session.conf.get("spark.sql.shuffle.partitions")
session = spark.conf.get("spark.yarn.am.memory")

df = spark.createDataFrame(data, schema=["Name", "Age", "City"])
Copy

Sortie

L’outil ajoute l’EWI SPRKPY1058 au code de sortie pour vous indiquer que ces méthodes ne sont pas prises en charge avec une clé spécifique à la plateforme.

data =
    [
      ("John", 30, "New York"),
      ("Jane", 25, "San Francisco")
    ]

#EWI: SPRKPY1058 => pyspark.sql.conf.RuntimeConfig.set method with this "spark.sql.shuffle.partitions" Platform specific key is not supported.
spark.conf.set("spark.sql.shuffle.partitions", "50")
#EWI: SPRKPY1058 => pyspark.sql.conf.RuntimeConfig.set method with this "spark.yarn.am.memory" Platform specific key is not supported.
spark.conf.set("spark.yarn.am.memory", "1g")

#EWI: SPRKPY1058 => pyspark.sql.conf.RuntimeConfig.get method with this "spark.sql.shuffle.partitions" Platform specific key is not supported.
spark.conf.get("spark.sql.shuffle.partitions")
#EWI: SPRKPY1058 => pyspark.sql.conf.RuntimeConfig.get method with this "spark.yarn.am.memory" Platform specific key is not supported.
spark.conf.get("spark.yarn.am.memory")

df = spark.createDataFrame(data, schema=["Name", "Age", "City"])
Copy

Correction recommandée

La correction recommandée consiste à supprimer ces méthodes.

data =
    [
      ("John", 30, "New York"),
      ("Jane", 25, "San Francisco")
    ]

df = spark.createDataFrame(data, schema=["Name", "Age", "City"])
Copy

Recommandations supplémentaires

SPRKPY1049

Avertissement

Ce code de problème est obsolète depuis Spark Conversion Core Version 2.1.9

Message : pyspark.sql.session.SparkSession.sparkContext a une solution de contournement

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.session.SparkSession.sparkContext qui dispose d’une solution de contournement.

Scénario

Entrée

Vous trouverez ci-dessous un exemple de création d’une session Spark et d’utilisation de la propriété SparkContext pour imprimer le nom de l’application (appName).

print("APP Name :"+spark.sparkContext.appName())
Copy

Sortie

L’outil ajoute l’EWI SPRKPY1049 indiquant qu’une solution de contournement peut être mise en œuvre.

#EWI: SPRKPY1049 => pyspark.sql.session.SparkSession.sparkContext has a workaround, see documentation for more info
print("APP Name :"+spark.sparkContext.appName())
Copy

Correction recommandée

SparkContext n’est pas pris en charge par SnowPark, mais vous pouvez accéder aux méthodes et propriétés de SparkContext directement à partir de l’instance de session.

## Pyspark
print("APP Name :"+spark.sparkContext.appName())
can be used in SnowPark removing the sparkContext as:
#Manual adjustment in SnowPark
print("APP Name :"+spark.appName());
Copy

Recommandations supplémentaires

SPRKPY1018

Avertissement

Ce code de problème est obsolète depuis Spark Conversion Core Version 4.8.0

Message : pyspark.sql.functions.date_sub a une solution de contournement

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.functions.date_sub qui dispose d’une solution de contournement.

Scénario

Entrée

Dans cet exemple, nous utilisons date_add pour calculer la date 5 jours avant la date actuelle pour le dataframe df.

col = df.select(date_sub(df.colName, 5))
Copy

Sortie

SMA renvoie l’EWI SPRKPY1018 sur la ligne où date_sub est utilisé, ce qui vous permet d’identifier l’endroit à corriger.

#EWI: SPRKPY1018 => pyspark.sql.functions.date_sub has a workaround, see documentation for more info
col = df.select(date_sub(df.colName, 5))
Copy

Correction recommandée

Importez snowflake.snowpark.functions, qui contient une implémentation pour la fonction date_sub.

from pyspark.sql.functions import date_sub
df.withColumn("date", date_sub(df.colName, 5))
Copy

Recommandation supplémentaire

SPRKPY1008

Message : pyspark.sql.context.HiveContext n’est pas requis

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil détecte l’utilisation de pyspark.sql.context.HiveContext.set qui n’est pas requis.

Scénario

Entrée

Dans cet exemple, il s’agit de créer une connexion à un magasin Hive.

from pyspark.sql import HiveContext
hive_context = HiveContext(sc)
df = hive_context.table("myTable")
df.show()
Copy

Sortie

Dans Snowflake, il n’y a pas de magasins Hive, donc le contexte Hive n’est pas requis. Vous pouvez toujours utiliser des fichiers parquet sur Snowflake. Consultez ce tutoriel pour en savoir plus.

#EWI: SPRKPY1008 => pyspark.sql.context.HiveContext is not required
hive_context = sc
df = hive_context.table("myTable")
df.show()
Copy

La variable sc fait référence à un objet de session SnowPark.

Correction recommandée

Pour le code de sortie de l’exemple, vous devez ajouter l”objet de session SnowPark de la manière suivante :

## Here manually we can add the Snowpark Session object via a json config file called connection.json
import json
from snowflake.snowpark import Session
jsonFile = open("connection.json")
connection_parameter = json.load(jsonFile)
jsonFile.close()
sc = Session.builder.configs(connection_parameter).getOrCreate()

hive_context = sc
df = hive_context.table("myTable")
df.show()
Copy

Recommandations supplémentaires

SPRKPY1059

Avertissement

Ce code de problème est obsolète depuis Spark Conversion Core Version 2.45.1

Message : pyspark.storagelevel.StorageLevel a une solution de contournement. Voir la documentation pour plus d’informations

Catégorie : Avertissement

Description

Actuellement, l’utilisation de StorageLevel n’est pas requise dans Snowpark car Snowflake contrôle le stockage. Pour plus d’informations, vous pouvez vous référer à l’EWI SPRKPY1072

Recommandations supplémentaires

SPRKPY1079

Message : L’argument de la fonction pyspark.context.SparkContext.setLogLevel n’est pas un niveau de journalisation PySpark valide.

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil SMA détecte l’utilisation de la fonction pyspark.context.SparkContext. setLogLevel avec un argument qui n’est pas un niveau de journalisation valide dans PySpark et, par conséquent, aucun équivalent n’a pu être déterminé dans Snowpark.

Scénario

Entrée

Ici le niveau de journalisation utilise « INVALID_LOG_LEVEL » qui n’est pas un niveau de journalisation Pyspark valide.

sparkSession.sparkContext.setLogLevel("INVALID_LOG_LEVEL")
Copy

Sortie

SMA ne peut pas reconnaître le niveau de journalisation « INVALID_LOG_LEVEL ». Même si SMA effectue la conversion, l’EWI SPRKPY1079 est ajouté pour indiquer un éventuel problème.

#EWI: SPRKPY1079 => INVALID_LOG_LEVEL is not a valid PySpark log level, therefore an equivalent could not be determined in Snowpark. Valid PySpark log levels are: ALL, DEBUG, ERROR, FATAL, INFO, OFF, TRACE, WARN
logging.basicConfig(stream = sys.stdout, level = logging.INVALID_LOG_LEVEL)
Copy

Correction recommandée

Assurez-vous que le niveau de journalisation utilisé dans la fonction pyspark.context.SparkContext.setLogLevel est un niveau de journalisation valide dans PySpark ou dans Snowpark et réessayez.

logging.basicConfig(stream = sys.stdout, level = logging.DEBUG)
Copy

Recommandations supplémentaires

SPRKPY1028

Message : pyspark.sql.readwriter.DataFrameReader.orc a une solution de contournement. Voir la documentation pour plus d’informations

Catégorie : Avertissement

Description

Ce problème apparaît lorsque l’outil SMA détecte une utilisation de la fonction pyspark.sql.readwriter.DataFrameReader.orc, qui dispose d’une solution de contournement.

Scénario

Entrée

Vous trouverez ci-dessous un exemple d’utilisation de la fonction pyspark.sql.readwriter.DataFrameReader.orc qui génère cet EWI. Dans cet exemple, la fonction orc est utilisée pour lire plusieurs fichiers .orc et utilise quelques options supplémentaires telles que mergeSchema et recursiveFileLookup pour affiner le comportement de lecture des fichiers.

file_paths = [
  "path/to/your/file1.orc",
  "path/to/your/file2.orc",
  "path/to/your/file3.orc",
]

df = session.read.orc(
  file_paths,
  mergeSchema="True",
  recursiveFileLookup="True"
)
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1028 au code de sortie pour vous indiquer que cette fonction n’est pas directement prise en charge par Snowpark, mais qu’il existe une solution de contournement.

file_paths = [
  "path/to/your/file1.orc",
  "path/to/your/file2.orc",
  "path/to/your/file3.orc",
]

#EWI: SPRKPY1028 => pyspark.sql.readwriter.DataFrameReader.orc has a workaround, see documentation for more info
df = session.read.orc(
  file_paths,
  mergeSchema="True",
  recursiveFileLookup="True"
)
Copy

Correction recommandée

Dans cette section, nous expliquons comment configurer le paramètre path et les options supplémentaires pour les faire fonctionner dans Snowpark.

1. Paramètre path

Snowpark exige que le paramètre path soit un emplacement de zone de préparation. Pour contourner le problème, vous pouvez créer une zone de préparation temporaire et ajouter chaque fichier .orc à cette zone de préparation en utilisant le préfixe file://.

2. Paramètres des options

Snowpark ne permet pas de définir les options supplémentaires comme paramètres de la fonction orc. Comme solution de contournement, vous pouvez utiliser la fonction Snowflake.snowpark.DataFrameReader.option pour spécifier ces paramètres en tant qu’options de DataFrameReader.

Note

Les options suivantes ne sont pas prises en charge par Snowpark :

  • compression

  • mergeSchema

Vous trouverez ci-dessous l’exemple complet de ce à quoi devrait ressembler le code d’entrée après avoir appliqué les suggestions mentionnées ci-dessus pour qu’il fonctionne dans Snowpark :

stage = f'{session.get_fully_qualified_current_schema()}.{_generate_prefix("TEMP_STAGE")}'
session.sql(f'CREATE TEMPORARY STAGE IF NOT EXISTS {stage}')

session.file.put(f"file:///path/to/your/file1.orc", f"@{stage}")
session.file.put(f"file:///path/to/your/file2.orc", f"@{stage}")
session.file.put(f"file:///path/to/your/file3.orc", f"@{stage}")

df = session.read.option(recursiveFileLookup, "True").orc(stage)
Copy

Recommandations supplémentaires

SPRKPY1038

Message : l’élément Spark n’est pas encore reconnu.

Catégorie : Erreur de conversion

Description

Ce problème apparaît lorsque votre code source contient un élément PySpark qui n’a pas été reconnu par l’outil SMA. Cela peut se produire pour différentes raisons, comme par exemple :

  • Un élément qui n’existe pas dans PySpark.

  • Un élément qui a été ajouté dans une version de PySpark et qui n’est pas encore pris en charge par SMA.

  • Une erreur interne de l’outil SMA lors du traitement de l’élément.

Il s’agit d’un code d’erreur générique utilisé par SMA pour tout élément non reconnu.

Scénario

Entrée

Vous trouverez ci-dessous un exemple d’utilisation d’une fonction qui n’a pas pu être reconnue par l’outil SMA car elle n’existe pas dans PySpark.

from pyspark.sql import functions as F
F.unrecognized_function()
Copy

Sortie

L’outil SMA ajoute l’EWI SPRKPY1038 au code de sortie pour vous indiquer que cet élément n’a pas pu être reconnu.

from snowflake.snowpark import functions as F
#EWI: SPRKPY1038 => pyspark.sql.functions.non_existent_function is not yet recognized
F.unrecognized_function()
Copy

Correction recommandée

Pour tenter d’identifier le problème, vous pouvez effectuer les validations suivantes :

  • Vérifiez si l’élément existe dans PySpark.

  • Vérifiez que l’élément est correctement orthographié.

  • Vérifiez que vous utilisez une version de PySpark prise en charge par SMA. Pour savoir quelle version de PySpark est prise en charge par SMA au moment de l’exécution de SMA, vous pouvez consulter la première page du fichier DetailedReport.docx.

S’il s’agit d’un élément PySpark valide, veuillez signaler que vous avez rencontré une erreur de conversion sur cet élément particulier en utilisant l’option Signaler un problème de l’outil SMA et incluez toute information supplémentaire que vous jugez utile.

Veuillez noter que si un élément n’a pas pu être reconnu par SMA, cela ne signifie pas qu’il n’est pas pris en charge par Snowpark. Vous devez consulter la documentation de Snowpark pour vérifier qu’un élément équivalent existe.

Recommandations supplémentaires

SPRKPY1069

Message : Si le paramètre partitionBy est une liste, Snowpark générera une erreur.

Catégorie : Avertissement

Description

Lors de l’utilisation de la méthode pyspark.sql.readwriter.DataFrameWriter.parquet avec le paramètre partitionBy, l’outil affiche l’EWI.

En effet, dans Snowpark, la méthode DataFrameWriter.parquet ne prend en charge que ColumnOrSqlExpr comme paramètre partitionBy.

Scénarios

Scénario 1

Code d’entrée :

Dans ce scénario, le paramètre partitionBy n’est pas une liste.

df = spark.createDataFrame([(25, "Alice", "150"), (30, "Bob", "350")], schema=["age", "name", "value"])

df.write.parquet(file_path, partitionBy="age")
Copy

Code de sortie :

L’outil ajoute l’EWI SPRKPY1069 pour vous indiquer que Snowpark génère une erreur si le paramètre est une liste.

df = spark.createDataFrame([(25, "Alice", "150"), (30, "Bob", "350")], schema=["age", "name", "value"])

#EWI: SPRKPY1069 => If partitionBy parameter is a list, Snowpark will throw and error.
df.write.parquet(file_path, partition_by = "age", format_type_options = dict(compression = "None"))
Copy

Correction recommandée

Il n’y a pas de correction recommandée pour ce scénario car l’outil ajoute toujours cet EWI au cas où le paramètre partitionBy est une liste. N’oubliez pas que Snowpark n’accepte que les emplacements Cloud utilisant une zone de préparation Snowflake.

df = spark.createDataFrame([(25, "Alice", "150"), (30, "Bob", "350")], schema=["age", "name", "value"])

stage = f'{Session.get_fully_qualified_current_schema()}.{_generate_prefix("TEMP_STAGE")}'
Session.sql(f'CREATE TEMPORARY STAGE IF NOT EXISTS {stage}').show()
Session.file.put(f"file:///path/to/data/file.parquet", f"@{stage}")

df.write.parquet(stage, partition_by = "age", format_type_options = dict(compression = "None"))
Copy
Scénario 2

Code d’entrée :

Pour ce scénario, le paramètre partitionBy est une liste.

df = spark.createDataFrame([(25, "Alice", "150"), (30, "Bob", "350")], schema=["age", "name", "value"])

df.write.parquet(file_path, partitionBy=["age", "name"])
Copy

Code de sortie :

L’outil ajoute l’EWI SPRKPY1069 pour vous indiquer que Snowpark génère une erreur si le paramètre est une liste.

df = spark.createDataFrame([(25, "Alice", "150"), (30, "Bob", "350")], schema=["age", "name", "value"])

#EWI: SPRKPY1069 => If partitionBy parameter is a list, Snowpark will throw and error.
df.write.parquet(file_path, partition_by = ["age", "name"], format_type_options = dict(compression = "None"))
Copy

Correction recommandée

Si la valeur du paramètre est une liste, remplacez-la par ColumnOrSqlExpr.

df.write.parquet(file_path, partition_by = sql_expr("age || name"), format_type_options = dict(compression = "None"))
Copy

Recommandations supplémentaires