0

I have essentially zero coding experience. I'm using GPT4 prompts to help me put together a simple print utility that generates a barcode and adds 1 to the last code printed in order for us to organize our inventory. The script works great when run with IDLE but when it's packaged it does not generate a barcode image and gives an error in cmd. GPT has tried numerous ways around this always resulting in the same error.

It has concluded that pyinstaller must be incompatible with the barcode pip(?) Here's the full script:

import tkinter as tk
from barcode import Code39
from barcode.writer import ImageWriter
from PIL import Image, ImageFont, ImageDraw
import sys
import os
import time
import threading

def resource_path(relative_path):
    try:
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(".")
    return os.path.join(base_path, relative_path)

font_path = resource_path('resources/ARLRDBD.ttf')


def get_next_number(filename):
    try:
        with open(filename, 'r') as f:
            lines = f.read().splitlines()  # splitlines method strips newline characters
        last_number = int(lines[-1])
    except FileNotFoundError:
        last_number = 54999  # start from 55000
    next_number = last_number + 1
    with open(filename, 'a') as f:
        f.write(f"{next_number}\n")  # append the next number to the file
    return last_number, next_number

def generate_barcode(number):
    code39 = Code39(str(number), writer=ImageWriter(), add_checksum=False)

    # Create the directory if it does not exist
    directory = 'barcodes'
    if not os.path.exists(directory):
        os.makedirs(directory)

    filename = os.path.join(directory, f"barcode_{number}.jpeg")  # Save the file in the directory

    barcode_img = code39.save(filename)

    img = Image.open(barcode_img)

    width_mm = 62
    height_mm = 29
    width_pixel = int(width_mm * (300 / 25.4))  
    height_pixel = int(height_mm * (300 / 25.4)) 
    img_resized = img.resize((width_pixel, height_pixel))

    draw = ImageDraw.Draw(img_resized)
    font = ImageFont.load_default()

    text_bbox = draw.textbbox((0, 0), str(number), font=font)
    text_width = text_bbox[2]
    x_position = (img_resized.width - text_width) / 2

    draw.text((x_position, img_resized.height - 50), str(number), font=font, fill=255)

    img_resized.save(barcode_img)
    return barcode_img


def print_file(barcode_img):
    time.sleep(1)  # let the system recognize the new file
    os.startfile(barcode_img, 'print')
    threading.Timer(60, os.remove, [barcode_img]).start()  # delay before deleting the file

def main():
    last_number, next_number = get_next_number("last_number.txt") 
    barcode_img = generate_barcode(next_number)
    print_file(barcode_img)

    # Adding 1 to the numbers displayed in the labels
    last_label.config(text="Last: " + str(last_number + 1))
    next_label.config(text="Next: " + str(next_number + 1))


root = tk.Tk()
root.geometry('400x400')  # Set the window size to 400x400
root.title("Auction Barcode Print Button")  # Set the window title

# Create the labels with default text
last_label = tk.Label(root, text="Last: ", font=('Arial', 14))
next_label = tk.Label(root, text="Next: ", font=('Arial', 14))

# Place the labels in the window
last_label.pack(pady=(50, 10))
next_label.pack(pady=(10, 20))

button_frame = tk.Frame(root, width=200, height=200)  # Frame to hold the button
button_frame.pack_propagate(0)  # prevents the frame to shrink
button_frame.pack(pady=(20,20))

button = tk.Button(button_frame, text="Print Barcode", command=main, relief=tk.RAISED)  
button.pack(fill=tk.BOTH, expand=1)  # Button fills the entire frame

root.mainloop()

And here's the error from cmd when this script is packaged and run:

Exception in Tkinter callback
Traceback (most recent call last):
  File "tkinter\__init__.py", line 1948, in __call__
  File "Auction_Label_4.py", line 72, in main
  File "Auction_Label_4.py", line 42, in generate_barcode
  File "barcode\base.py", line 65, in save
  File "barcode\codex.py", line 74, in render
  File "barcode\base.py", line 105, in render
  File "barcode\writer.py", line 265, in render
  File "barcode\writer.py", line 439, in _paint_text
  File "PIL\ImageFont.py", line 1008, in truetype
  File "PIL\ImageFont.py", line 1005, in freetype
  File "PIL\ImageFont.py", line 255, in __init__
OSError: cannot open resource

The script does however generate the 'last_number' txt file and the 'barcodes' folder, it just doesn't generate a barcode.

Thank you for giving this post a look.

Shaken89
  • 1
  • 1

1 Answers1

0

To resolve this issue, make sure that the font file specified in the font_path variable (ARLRDBD.ttf) is located in the correct directory. The font file should be present in the resources subdirectory relative to the location of your script.

Additionally, ensure that the resources subdirectory is included when creating the executable or running the script. If you are using PyInstaller or a similar tool to create the executable, make sure the resources directory is included in the build process.

By addressing these issues, the code should be able to access the font file and resolve the OSError you encountered.

Rahul
  • 1
  • 1
  • Thanks. I did verify what you suggested but I am still getting the same result. I have the font in a 'resources' folder in the same directory as the .py script. Is there another way I can verify that pyinstaller is packaging the resource with the script? – Shaken89 Jun 11 '23 at 16:02
  • @Shaken89 you may find this tutorial useful: https://www.pythonguis.com/tutorials/packaging-pyqt5-applications-pyinstaller-macos-dmg/ – TheTridentGuy supports Ukraine Jun 11 '23 at 22:55