Python Forum

Full Version: str.decode to PNG not working with MySql
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Good day everyone.
I have inherited a Python 2.7 script that pulls records from a mysql database and creates png files to export my product's images. The line that worked for years is "fh.write(str.decode('base64'))" and the table "images" has a column named "imageFull" with a Collation of 'utf8_general_ci'

Last month the vendor updated the software and the table structure has changed. The column "imageFull" now has a Collation of 'utf8mb4_unicode_ci' and the write command fails. I tried updating to Python 3.13(64-bit)

I can't change the column structure as it is not my application. I can't say why they are storing images in this way. The vendor has no responsibility to helping with this export script.

So the question is "Do I need to use a decode other than 'base64'? Does it matter if i'm on python 2.7 or 3.13? Is there an alternate command to use for the write string? "


Here is a larger chunk of the code incase it helps.
try:
			#Convert image string to its png form
			print("Converting full size image...")
			str = row[1]#full size image
			fh = open(finalImageName, "wb")
			fh.write(str.decode('base64'))
			fh.close()
			totalSuccessLarge+=1
		except:
			print("This large image failed...skipping and continuing process...")
			totalFailLarge+=1
			time.sleep(5)
			pass
		
		try:
			print("Converting thumbnail size image...")
			str = row[2]#thumb image
			fh = open(finalImageName2, "wb")
            fh.write(str.decode('base64'))
			fh.close()
			totalSuccessThumb+=1
		except:
			print("This thumbnail image failed...skipping and continuing process...")
			totalFailThumb+=1
			time.sleep(5)
			pass
Good morning.
The output of the script is as follows.

Part number for this image = zzz test part 1
Combined part num with .png = zzz test part 1.png
Final image name 2 (where small images are saved) = C:\Python27\thumbs\zzz test part 1.png
Converting full size image...
1
2
This large image failed...skipping and continuing process...
Converting thumbnail size image...
This thumbnail image failed...skipping and continuing process...
Moving large images into their folder...
PROCESS COMPLETE!
Large Image Success total = 0
Large Image Failed Total = 1
Thumb Image Success total = 0
Thumb Image Failed Total = 1
Try use base64 module instead of str.decode('base64').
This should work for Python 3.13.
import base64

# Convert image string to bytes in base64, then decode
str_data = row[1]  # full-size image
image_data = base64.b64decode(str_data) 

with open(finalImageName, "wb") as fh:
    fh.write(image_data)
Thumbnail conversion:
str_data_thumb = row[2]  # thumbnail image
thumb_image_data = base64.b64decode(str_data_thumb)

with open(finalImageName2, "wb") as fh:
    fh.write(thumb_image_data)
You might need to encode it back to bytes before decoding from base64. For example:
str_data = row[1].encode('utf-8')  # Ensure string is encoded as bytes
image_data = base64.b64decode(str_data)
And try not to use str as variable name,Python use this name.
Hi.
Thank you for the suggestions. I beleve I implemented your changes. Unfortunately I still get the same error.

try:
			#Convert image string to its png form
			print("Converting full size image...")
			str_data = row[1].encode('utf-8')  # Ensure string is encoded as bytes
			image_data = base64.b64decode(str_data)
			#FB 19.7 was utf8_general_ci  while FB 24.3 is utf8mb4_unicode_ci
			with open(finalImageName, "wb") as fh: fh.write(image_data)
			fh.close()
			totalSuccessLarge+=1
		except:
I don't do consulting time,i can try to help you here on forum.
Try this code.
import base64
import time
import mysql.connector
from mysql.connector import errorcode
import shutil
import os
import glob

source_dir = "C:/python27"
dst = 'C:/python27/largeSize'
totalSuccessLarge = 0
totalFailLarge = 0
totalSuccessThumb = 0
totalFailThumb = 0

print("WELCOME TO SUPER MEGA AWESOME IMAGE CONVERTER!")

# Load config variables
configVariables = []
filepath = 'imgConvert-Config.txt'
with open(filepath, 'r') as f:
    configVariables = f.readlines()

print("Loading config file...")
pw = os.environ.get('DB_PASSWORD')
if not pw:
    raise ValueError("Database password not found in environment variables.")
database = configVariables[0].strip()
user = configVariables[1].strip()
host = configVariables[2].strip()
pathFull = configVariables[3].strip()
pathSmall = configVariables[4].strip()

print("Connecting to DB...")
try:
    cnx = mysql.connector.connect(user=user, password=pw, host=host, port=3306, database=database)
    cursor = cnx.cursor()
    print("Executing queries...")
    sql_select_Query = "SELECT * FROM image"
    cursor.execute(sql_select_Query)
    records = cursor.fetchall()

    print("Total number of rows in image is - ", cursor.rowcount)
    for row in records:
        # Extract data
        img_id, full_size_image, thumbnail_image, record_id = row
        print(f"Id = {img_id}")
        print(f"Full Size image = {full_size_image}")
        print(f"Thumbnail image = {thumbnail_image}")
        print(f"recordID = {record_id}\n")

        # Get part number
        sql_select_Query3 = "SELECT num FROM part WHERE id = %s"
        cursor.execute(sql_select_Query3, (record_id,))
        partNum = cursor.fetchone()[0]
        print(f"Part number for this image = {partNum}")

        # Prepare file paths
        finalImageName = os.path.join(dst, f"{partNum}.png")
        finalImageName2 = os.path.join(pathSmall, f"{partNum}.png")

        # Ensure directories exist
        os.makedirs(dst, exist_ok=True)
        os.makedirs(pathSmall, exist_ok=True)

        # Convert full-size image
        try:
            print("Converting full size image...")
            image_data = base64.b64decode(full_size_image)
            with open(finalImageName, "wb") as fh:
                fh.write(image_data)
            totalSuccessLarge += 1
        except Exception as e:
            print(f"This large image failed... {e}")
            totalFailLarge += 1
            continue
        # Convert thumbnail image
        try:
            print("Converting thumbnail size image...")
            thumb_image_data = base64.b64decode(thumbnail_image)
            with open(finalImageName2, "wb") as fh:
                fh.write(thumb_image_data)
            totalSuccessThumb += 1
        except Exception as e:
            print(f"This thumbnail image failed... {e}")
            totalFailThumb += 1
            continue

except mysql.connector.Error as err:
    if err.errno == errorcode.ER_ACCESS_DENIED_ERROR:
        print("Something is wrong with your username or password")
    elif err.errno == errorcode.ER_BAD_DB_ERROR:
        print("Database does not exist")
    else:
        print(err)
finally:
    if 'cursor' in locals():
        cursor.close()
    if 'cnx' in locals():
        cnx.close()

print("PROCESS COMPLETE!")
print(f"Large Image Success total = {totalSuccessLarge}")
print(f"Large Image Failed Total = {totalFailLarge}")
print(f"Thumb Image Success total = {totalSuccessThumb}")
print(f"Thumb Image Failed Total = {totalFailThumb}")
Hi.
Thank you for helping. Your way of doing this is very interesting. Running this code I receive an error.

Executing queries...
Total number of rows in image is - 28345
Traceback (most recent call last):
File "C:\Python27\imageconverter-forum.py", line 46, in <module>
img_id, full_size_image, thumbnail_image, record_id = row
ValueError: too many values to unpack (expected 4)
Hi again. I have some progress. Smile
If I remove the "= row" from the line "img_id, full_size_image, thumbnail_image, record_id = row" I get past this error.
Then at the top under the includes I add:
img_id = 0
full_size_image = ""
thumbnail_image = ""
record_id = 0
I get past the next error of "full_size_image" is not defined.

But then I hit the next landmine of:
Traceback (most recent call last):
File "C:\Python27\imageconverter-forum.py", line 60, in <module>
partNum = cursor.fetchone()[0]
TypeError: 'NoneType' object is not subscriptable
Try before accessing the result, check if cursor.fetchone() returned a result:
cursor.execute(sql_select_Query3, (record_id,))
part_num_row = cursor.fetchone()
if part_num_row:
    partNum = part_num_row[0]
    print(f"Part number for this image = {partNum}")
else:
    print(f"No part number found for record ID {record_id}")
    totalFailLarge += 1
    totalFailThumb += 1
    continue  # Skip to the next iteration
Hello.
I added that change and get hundreds of lines that say:

No part number found for record ID = 0
Id = 0
Full size image =
thumbnail =
recordID = 0
Your image table may has entries where recordID is 0.
Since there is no part with id = 0, the query to get the partNum fails.
The full_size_image and thumbnail_image fields are empty (''), which means there's no image data to process.
Try this.
import base64
import mysql.connector
from mysql.connector import errorcode
import os

source_dir = "C:/python27"
dst = 'C:/python27/largeSize'
totalSuccessLarge = 0
totalFailLarge = 0
totalSuccessThumb = 0
totalFailThumb = 0

print("WELCOME TO SUPER MEGA AWESOME IMAGE CONVERTER!")

# Load config variables
configVariables = []
filepath = 'imgConvert-Config.txt'
with open(filepath, 'r') as f:
    configVariables = f.readlines()

print("Loading config file...")
pw = "xxxx9999"
database = configVariables[0].strip()
user = configVariables[1].strip()
host = configVariables[2].strip()
pathFull = configVariables[3].strip()
pathSmall = configVariables[4].strip()

print("Connecting to DB...")
try:
    cnx = mysql.connector.connect(user=user, password=pw, host=host, port=3306, database=database)
    cursor = cnx.cursor()
    print("Executing queries...")

    # Modified SQL query to filter out invalid entries
    sql_select_Query = """
    SELECT id, full_size_image, thumbnail_image, record_id
    FROM image
    WHERE record_id > 0
      AND full_size_image IS NOT NULL AND full_size_image != ''
      AND thumbnail_image IS NOT NULL AND thumbnail_image != ''
    """
    cursor.execute(sql_select_Query)
    records = cursor.fetchall()

    print("Total number of valid rows in image is - ", cursor.rowcount)
    for row in records:
        img_id, full_size_image, thumbnail_image, record_id = row
        print(f"Id = {img_id}")
        print(f"Full Size image = {full_size_image}")
        print(f"Thumbnail image = {thumbnail_image}")
        print(f"recordID = {record_id}\n")

        # Query for part number
        sql_select_Query3 = "SELECT num FROM part WHERE id = %s"
        cursor.execute(sql_select_Query3, (record_id,))
        part_num_row = cursor.fetchone()
        if part_num_row:
            partNum = part_num_row[0]
            print(f"Part number for this image = {partNum}")
        else:
            print(f"No part number found for record ID = {record_id}")
            totalFailLarge += 1
            totalFailThumb += 1
            continue  # Skip to the next image

        # Prepare file paths
        finalImageName = os.path.join(dst, f"{partNum}.png")
        finalImageName2 = os.path.join(pathSmall, f"{partNum}.png")

        # Ensure directories exist
        os.makedirs(dst, exist_ok=True)
        os.makedirs(pathSmall, exist_ok=True)

        # Convert full-size image
        try:
            print("Converting full size image...")
            image_data = base64.b64decode(full_size_image)
            with open(finalImageName, "wb") as fh:
                fh.write(image_data)
            totalSuccessLarge += 1
        except Exception as e:
            print(f"This large image failed... {e}")
            totalFailLarge += 1
            continue

        # Convert thumbnail image
        try:
            print("Converting thumbnail size image...")
            thumb_image_data = base64.b64decode(thumbnail_image)
            with open(finalImageName2, "wb") as fh:
                fh.write(thumb_image_data)
            totalSuccessThumb += 1
        except Exception as e:
            print(f"This thumbnail image failed... {e}")
            totalFailThumb += 1
            continue

except mysql.connector.Error as err:
    if err.errno == errorcode.ER_ACCESS_DENIED_ERROR:
        print("Something is wrong with your username or password")
    elif err.errno == errorcode.ER_BAD_DB_ERROR:
        print("Database does not exist")
    else:
        print(err)
finally:
    if 'cursor' in locals():
        cursor.close()
    if 'cnx' in locals():
        cnx.close()

print("PROCESS COMPLETE!")
print(f"Large Image Success total = {totalSuccessLarge}")
print(f"Large Image Failed Total = {totalFailLarge}")
print(f"Thumb Image Success total = {totalSuccessThumb}")
print(f"Thumb Image Failed Total = {totalFailThumb}")