How to Install Python Barcode SDK via Pip on Apple M1 Mac

Someone may be curious about whether Intel-based Python apps can work well on Apple M1 Mac. I recently did a test with Dynamsoft Python Barcode SDK, which is built with native x86_64 libraries and CPython. It turned out that there was no issue using pip to install the wheel package and running my Python barcode reader app.

Installing Pip and Python Barcode Wheel Package

When you open the terminal app and type in Python3 the first time, a prompt dialog will pop up for installing the command line developer tools.

Apple M1 Python3 Installation

Click Install and wait a while for installing the relevant tools. After that, you can run python3 successfully in the terminal.

The next step is to install pip:

curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
python3 get-pip.py 

Once pip is ready, you can try to install Dynamsoft Python Barcode SDK:

python3 -m pip install dbr

Don’t be surprised if you see the failure message.

pip install on Apple M1

You are trying to install an x86_64 wheel package on ARM64 architecture. However, don’t be frustrated because Rosetta 2 can make it work. Let’s take a look at the Python3 architecture:

% file $(which python3)
/usr/bin/python3: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64e:Mach-O 64-bit executable arm64e]
/usr/bin/python3 (for architecture x86_64):	Mach-O 64-bit executable x86_64
/usr/bin/python3 (for architecture arm64e):	Mach-O 64-bit executable arm64e

As you can see the Python 3 is a universal app, supporting x86_64. Therefore, we can install the x86_64 wheel package by specifying the arch:

arch -x86_64 $(which python3) -m pip install dbr

Congratulations! You have installed Dynamsoft Python Barcode SDK. From now on, you can get started to create a barcode scanning app with a webcam.

Building Webcam-based Python Barcode Reader on Apple M1 Mac

Install OpenCV-Python for capturing webcam video stream:

arch -x86_64 $(which python3) -m pip opencv-python

Open a camera and display the video stream in real-time:

import cv2 as cv
cap = cv.VideoCapture(0)
while True:
    _ret, frame = cap.read()

    if not _ret:
        break
        
    cv.imshow('BarcodeReader', frame)

    ch = cv.waitKey(1)
    # ESC
    if ch == 27:
        break

Since scanning barcode is a CPU-intensive task, we should run it in Python Process rather than Python thread:

from dbr import *
from multiprocessing import Process, Queue

def process_barcode_frame(license, frameQueue, resultQueue):
    # Create Dynamsoft Barcode Reader
    reader = BarcodeReader()
    # Apply for a trial license: https://www.dynamsoft.com/customer/license/trialLicense
    reader.init_license(license)
    settings = reader.get_runtime_settings()
    settings.max_algorithm_thread_count = 1
    reader.update_runtime_settings(settings)

    while True:
        results = None

        try:
            frame = frameQueue.get(False, 10)
            if type(frame) is str:
                break
        except:
            continue

        try:
            frameHeight, frameWidth, channel = frame.shape[:3]
            results = reader.decode_buffer_manually(np.array(frame).tobytes(), frameWidth, frameHeight, frame.strides[0], EnumImagePixelFormat.IPF_RGB_888)
        except BarcodeReaderError as error:
            print(error)

        try:
            resultQueue.put(results, False, 10)
        except:
            pass

barcodeScanning = Process(target=process_barcode_frame, args=(license, frameQueue, resultQueue))
barcodeScanning.start()

Note: you need a valid SDK license as well.

In the main process, create two queues for continuously sending image frames and receiving barcode scanning results:

frameQueue = Queue(size)
resultQueue = Queue(size)

while True:
    _ret, frame = cap.read()

    if not _ret:
        break

    try:
        results = resultQueue.get(False, 10)
    except:
        pass
        
    cv.imshow('BarcodeReader', frame)

    # Append a frame to the frame queue
    try:
        frameQueue.put(frame.copy(), False, 10)
    except:
        pass

    ch = cv.waitKey(1)
    # ESC
    if ch == 27:
        break

Now, we can test the Python barcode program:

arch -x86_64 $(which python3) barcode_scanning.py license.txt

One more thing, you may fail to run the app due to the camera permission restriction. Instead of the terminal app, you can install iTerm2 to request the camera access.

iTerm2

Finally, we can do barcode scanning on Apple M1 Mac.

Python Barcode Reader on Apple M1 Mac

Source Code

https://gist.github.com/yushulx/c6666905d083d26b4d51316530faec56