Simpan dan ambil objek python acar ke / dari kepingan salju
sesuai pertanyaan, saya mencoba menyimpan objek python yang dipetik ke kepingan salju, untuk mendapatkannya kembali di kemudian hari. Bantuan dalam hal ini akan sangat dihargai:
Definisi tabel kepingan salju:
CREATE OR REPLACE TABLE <db>.<schema>.TESTING_MEMORY (
MODEL_DATETIME DATETIME,
SCALARS VARIANT
;
Kode Python:
import numpy as np
import pandas as pd
import pickle
from datetime import datetime
import snowflake.connector
from snowflake.connector.pandas_tools import write_pandas
from sklearn.preprocessing import StandardScaler
def create_snowflake_connection():
conn = snowflake.connector.connect(
user='<username>',
account='<account>',
password = '<password>',
warehouse='<wh>',
database='<db>',
role='<role>',
schema='<schema>'
)
return conn
memory = {}
np.random.seed(78)
df = pd.DataFrame({
'x1': np.random.normal(0, 2, 10000),
'x2': np.random.normal(5, 3, 10000),
'x3': np.random.normal(-5, 5, 10000)
})
scaler = StandardScaler()
scaler.fit(df)
scaled_df = scaler.transform(df)
scaled_df = pd.DataFrame(scaled_df, columns=['x1', 'x2', 'x3'])
memory['SCALARS'] = pickle.dumps(scaler)
ctx = create_snowflake_connection()
# Write to snowflake
db_dat = pd.DataFrame([list(memory.values())], columns=list(memory.keys()))
db_dat.insert(0, 'MODEL_DATETIME', datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"))
success, nchunks, nrows, _ = write_pandas(conn=ctx, df = db_dat, table_name = 'TESTING_MEMORY')
# retreive from snowflake
cur = ctx.cursor()
sql = """
SELECT hex_encode(SCALARS)
FROM <db>.<schema>.TESTING_MEMORY
QUALIFY ROW_NUMBER() OVER (ORDER BY MODEL_DATETIME DESC) = 1
"""
cur.execute(sql)
returned = cur.fetch_pandas_all()
cur.close()
ctx.close()
Jawaban
Sepertinya Anda mencoba memasukkan byteobjek python ke dalam Snowflake variantyang tidak akan berhasil untuk Anda.
Jawaban ini agak mirip dengan yang disarankan oleh jawaban lain di sini kecuali, daripada menggunakan varcharbidang untuk menyimpan biner berenkode base64, gunakan binarytipe sebagai gantinya. pengkodean base64 sekitar 30% lebih besar dari biner dari apa yang saya baca di suatu tempat.
Buat tabel dengan tipe data biner:
create or replace table testdb.public.test_table (obj binary);
Hex menyandikan objek yang diawetkan, menulisnya, membacanya kembali dan memanggil metode di atasnya:
import pickle
import snowflake.connector
# This is the object we're going to store in Snowflake as binary
class PickleMe:
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
def say_hello(self):
print(f'Hi there, {self.first_name} {self.last_name}')
# Create the object and store it as hex in the 'hex_person' variable
person = PickleMe('John', 'Doe')
hex_person = pickle.dumps(person).hex()
with snowflake.connector.connect(
user="username",
password="password",
account="snowflake_account_deets",
warehouse="warehouse_name",
) as con:
# Write pickled object into table as binary
con.cursor().execute(f"INSERT INTO testdb.public.test_table values(to_binary('{hex_person}', 'HEX'))")
# Now get the object back and put it into the 'obj' variable
(obj,) = con.cursor().execute(f"select obj from testdb.public.test_table").fetchone()
# Deserialise object and call method on it
person_obj = pickle.loads(obj, encoding='HEX')
person_obj.say_hello()
Output di atas adalah
Halo, John Doe
Mungkin ada cara yang lebih baik untuk melakukan ini (penafian: Saya baru mengenal Python), tetapi ini sepertinya berhasil dan didasarkan pada jawaban di sini: Bagaimana saya bisa mengawetkan objek python ke dalam file csv?
Ubah definisi tabel sql
CREATE OR REPLACE TABLE db.schema.TESTING_MEMORY ( MODEL_DATETIME DATETIME, SCALARS VARCHAR );
2 Perubahan ke Kode Python - umum
import base64
3 Perubahan pada kode Python (tulis ke bagian kepingan salju di atas)
# Write to snowflake
db_dat = pd.DataFrame([list(memory.values())], columns=list(memory.keys()))
db_dat.insert(0, 'MODEL_DATETIME', datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"))
pickled_columns = ['SCALARS']
for column in pickled_columns:
b64_bytes = base64.b64encode(db_dat[column].values[0])
db_dat[column] = b64_bytes.decode('utf8')
success, nchunks, nrows, _ = write_pandas(conn=ctx, df = db_dat, table_name = 'TESTING_MEMORY')
Perubahan pada kode Python - ambil dari kepingan salju
cur = ctx.cursor() sql = """ SELECT * FROM db.schema.TESTING_MEMORY QUALIFY ROW_NUMBER() OVER (ORDER BY MODEL_DATETIME DESC) = 1 """ cur.execute(sql) returned = cur.fetch_pandas_all() for column in pickled_columns: returned[column] = base64.b64decode(returned[column].values[0]) new_dict = returned.to_dict('list') for key,val in new_dict.items(): new_dict[key] = val[0]