UPC/EAN barcode script

Ken Roberts alisonken1 at juno.com
Sat Jan 10 04:24:00 CET 2004


Here's a quick routine that I hacked out to verify UPC-A/E and EAN-13/8 barcodes.

Anyone have any suggestions how to improve it?

================== Test script ==============
import ean

# Below codes taken from http://www.barcodeisland.com examples
# UPC-E codes to expand/verify
e = { 0: '01278907',
      1: '01278916',
      2: '01278925',
      3: '01238935',
      4: '01248934',
      5: '01258933',
      6: '01268932',
      7: '01278931',
      8: '01288930',
      9: '01298939',
      10: '01291944',
      11: '01291155',
      12: '01291162',
      13: '01291179',
      14: '01291186' }

# UPC-A codes to verify/compress
a = { 0: '012000007897',
      1: '012100007896',
      2: '012200007895',
      3: '012300000895',
      4: '012400000894',
      5: '012500000893',
      6: '012600000892',
      7: '012700000891',
      8: '012800000890',
      9: '012900000899',
      10: '012910000094',
      11: '012911000055',
      12: '012911000062',
      13: '012911000079',
      14: '012911000086' }

print 'checking upca2e ...'
for i in a.keys():
      t1=a[i]
      t2=ean.upca2e(t1)
      print 'key ', i, ':', t1, ean.upcaValid(t1)
      print 'upce', i, ':', t2, ean.upceValid(t2)

print
print 'Checking upce2a ...'
for i in e.keys():
      t1=e[i]
      print 'key', i, ':', t1, ean.upceValid(t1)

================ Barcode script ==============

"""
ean.py
See http://www.barcodeisland.com for UPC/EAN specs

Routines for verifying UPC/EAN codes and generating check digit

UPC-A is actually EAN13 code with a "0" prepended to it. The Barcode
Association has designated that all programs should be converted to
EAN by Jan 01, 2005.

Routines for UPC-A/UPC-E barcodes.

UPC is basically EAN13 with an extra leading '0' to bring the length
to 13 characters.

Check digit is calculated using ean13CheckDigit('0'+UPCA).

UPC-A is 12 characters in length with [12] being the check digit.
UPC-E is a compressed (convoluted algorithm) UPC-A with extraneous
middle 0 digits removed.

"""

__version__ = "$Revision: 0.4$"

codeLength = { "EAN13": 13,
               "EAN8": 8,
               "UPCA": 12,
               "UPCE": 8 }

def __lenCheck(chk, _type='EAN13'):
    return (len(chk) == codeLength[_type]) or \
       (len(chk) == codeLength[_type]-1)


def __sumDigits(chk, start=0, end=1, step=2, mult=1):
    return reduce(lambda x, y: int(x)+int(y), list(chk[start:end:step])) * mult

def eanCheckDigit(chk, code='EAN13'):
    """Returns the checksum digit of an EAN-13/8 code"""
    if chk.isdigit() and __lenCheck(chk):
        if code == 'EAN13':
            m0=1
            m1=3
        elif code == 'EAN8':
            m0=3
            m1=1
        else:
            return None

        _len = codeLength[code]-1
        t = 10 - (( __sumDigits(chk, start=0, end=_len, mult=m0) + \
                    __sumDigits(chk, start=1, end=_len, mult=m1) ) %10 ) %10

        if t == 10:
            return 0
        else:
            return t

    return None

def ean13Valid(chk):
    """Verify if code is valid EAN13 barcode.  Returns True|False"""
    return chk.isdigit() and __lenCheck(chk) and \
           (int(chk[-1]) == eanCheckDigit(chk))

def ean8CheckDigit(chk):
    """Returns the checksum digit of an EAN8 code"""
    return eanCheckDigit(chk, code='EAN8')

def ean8Valid(chk):
    """Verify if code is valid EAN8 barcode. Returns True|False"""
    if chk.isdigit() and len(chk) == codeLength["EAN8"]:
        return int(chk[-1]) == ean8CheckDigit(chk)
    return False

# UPC codes below

def upcaCheckDigit(chk):
    if chk is not None:
        return eanCheckDigit('0'+chk)
    return None

def upcaValid(chk):
    if chk is not None:
        return ean13Valid('0'+chk)
    return False

def upca2e(chk):
    t = None
    if chk.isdigit() and __lenCheck(chk, 'UPCA'):
        if '012'.find(chk[3]) >= 0 and chk[4:8] == '0000':
            t=chk[:3]+chk[8:11]+chk[3]
        elif chk[4:9] == '00000':
            t=chk[:4]+chk[9:11]+'3'
        elif chk[5:10] == '00000':
            t = chk[:5]+chk[10]+'4'
        elif '5678'.find(chk[10]) >= 0 and chk[6:10] == '0000':
            t=chk[:6]+chk[10]
        else:
            t=None

        # Check digit
        if t is not None:
            if upcaValid(chk):
                t=t+chk[-1]
            elif len(chk) == codeLength["UPCA"]-1:
                t=t+str(upcaCheckDigit(chk))
            else:
                t=None
    return t

def upce2a(chk):
    t=None
    if chk.isdigit() and __lenCheck(chk, 'UPCE'):
        if '012'.find(chk[6]) >= 0:
            t=chk[:3]+chk[6]+'0000'+chk[3:6]
        elif chk[6] == '3':
            t=chk[:4]+'00000'+chk[4:6]
        elif chk[6] == '4':
            t=chk[:5]+'00000'+chk[5]
        elif '5678'.find(chk[6]) >= 0:
            t=chk[:6]+'0000'+chk[6]
        else:
            t=None

        if t is not None:
            if len(chk) == codeLength["UPCE"] - 1:
                t=t+str(upcaCheckDigit(t))
            elif len(chk) == codeLength['UPCE'] and \
                 int(chk[-1]) == upcaCheckDigit(t):
                t=t+chk[-1]
            else:
                t=None
    return t
    
def upceValid(chk):
    return len(chk) == codeLength["UPCE"] and upcaValid(upce2a(chk))

def upceCheckDigit(chk):
    if chk is not None:
        return upcaCheckDigit(upce2a(chk))
    return None



More information about the Python-list mailing list