Roland's homepage

My random knot in the Web

Including binary data in Python scripts

Sometimes I need to use some binary data (e.g. a bitmap image) in a Python script. In a package, you can store this data portable in a data subdirectory of a modules using the package_data argument of setuptools.setup. This won’t work in a standalone script. You can of course make your script into a package, but here I want to show an alternative solution.

Preparing the data

For example, let’s start with this image:

Python powered logo

This is an 8-bit RGBA image. Since logo’s like this typically have few colors, we can make it smaller by converting it to a colormapped image.

convert python-powered-w-200x80.png PNG8:python-powered-w-200x80-cmap.png

This reduces the file size from 8758 bytes to 2483 bytes.

For non-image binary data, it might make sense to compress it with one of the compression formats that Python can use natively, like zlib, bz2 or lzma.

Converting to Python

Using the following code, we can convert the image or data file to Python code that can be included into our script.

import base64
import os

def to_include(path):
    linelen = 74
    with open(path, 'rb') as img:
        data = base64.b85encode(img.read()).decode('ascii')
    i = 0
    print('# ' + path)
    print('data = base64.b85decode(')
    while i < len(data):
        print("    '" + data[i:i+linelen] + "'")
        i += linelen
    print(")" + os.linesep)

So we run:

to_include('python-powered-w-200x80-cmap.png')

The result is:

# python-powered-w-200x80-cmap.png
data = base64.b85decode(
    'iBL{Q4GJ0x0000DNk~Le0002U0000`2m=5B0Bf_#f&c&j1ZP1_K>z@;j|==^1poj5AY({UO#lF'
    'TCIA3{ga82g0001h=l}q9FaQARU;qF*m;eA5aGbhPJOBUy_E1bzMgRZ*%*@QYySrv)W{8N0?(Y'
    'A)%-xy0-H58pcdE>0nY&epyF_=YGk2<0h^l6YyLXwpcdEOYyUgzY|IFR)GiItYW|?M)s;ax)-R'
    '|z0nVCd)ncdy)h`Y>pnau9)?%mzpcXxNHs;ax)?yAh)-R}QHh`U6Hs{jAY|J_yp-Ddypng8y)|'
    'I9Q0|L*_HMF0QYGk3dYnauy)cmM8)|J{iH-9-QHs{ihHh`ZgYyUe@H?jlupcbTeYh?!N0nTVOY'
    'Rd<>H?#zg)yP2xH%-!9)%*<7pyZ_8pGgWspRfu<pszhdpGiHcHcZkf)-I=P)|NpzdM6#a%0004'
    'EOGiWihy@);00007bV*G`2jdGE4ImUb|L$P`00)&xL_t(&-tC)vdzwfTheuR2CU#r3aV4}MN!x'
    'gLYufD6(MqG)6|vd<{$FP2%1uB9jZK~>zds_(g*orcIdkD50KDi$FM82&m6Lw81&6`N=L?VAL{'
    'To4Pb#Np)#}-+-(J5d*W~&$1Zk8{t5k2#JvD!SW+3%S)zx`GuUgLuq;*z}135pJ4`aWg909~P9'
    '@`)n#Y1r9^G5(_VEZc#AfHBooHw5hNC}yLhA&!?Am{3H0VyN%-;t|IB*+1#uH%5b-vRPw=M%JC'
    'PV?RBSwQrh9`RTm2&l5dwJOQgrFI^x%`62*JMZQd@_A&6lxK25Bn4G!dwUhVK=KRv)?@Pm8yYf'
    'cRW9pSuQGrb1fqajWj##|rfNrma2wsRAq5DF!G{ooD&(<k4Wv|H_7wzCP(wL<q2ZQeKtisCq~t'
    'W+aP7tq(V6w6nBL}DMqVJM_5ty%#w59PAk2ddR#N9(fUih-$t~^{IvxmavYiTq_prvy<~=|O+C'
    'dP&3LO!IcV}u4oGbYUgjUW4LE7m->cybS*+2lBV$y>sq=Mv+f&vMSj38lU1z`~?3ZnR|W;a40A'
    '4=uQ=|@+eJe_TUTz81Nz5WgmB?Cyon{;`g34jz&sxgX+k^X?IJB$Y@P#gCGQRsS^8sw^4%?2_U'
    'jSoE{`?%I+H8aSd6AO~h79)EEd*hEiKnA@S5RFcqI7tgzkp!ZL$OWd~&((cEMlm3K4bFS(TPhI'
    '$f|%Q05EDQ?RQCcI_@^!(2;UzSf=eE;LU+?5Kyu!SSfETPLCS(4uR|b{APC!y7r0AF?q-l|&UI'
    'c+iv#h{6?Tyl<f9-+4crXke2X4M3I^GO>#lvs5JRDxb)EZN+t6b`$o5x}48HkI36ktt5g-lF4S'
    ')>B0T6a5@|_zDcHC%71=k8AaIgx2xHZ^<k`Clb5aa@Y(I75Jh;^D|D3bs9qvZ@k!l&PYH-q6c{'
    'G;oxUFh1arAvwwo#B-asVoR`6$+8T;7bT3UhVXU32}WE1F3-F*APfIHHg5eNL;6h9B)G$uK}2Z'
    'Jj);L$(CyVqsGDYQ2^vj2H<uS1{tIU$@%w#2UpDg<n(>5R4Uc{YSaN3c1M{(v^@?*DHKKVDdwH'
    '~`1b240>s<PCxJ+9p|?`PiWrd-lsxSBLb{m{icBDqQV@K*Ca&!mLBr8U2f(je8pVKk4~v^$$$I'
    '#R@qx89Yn1`G>0|@}dbG8Yx4J!=!t2N>0DpFbKt}r;aR~ht0%;Jx5&`M%Z-jtMGbZC(kmC%1jv'
    'z=+$dEnNgwvRuVi3fA*^?e*{4_v9(^d)G3W6LrL}u|I!B<+}=#(V@@<qgsz4aZ=<FXn7kV|2Z@'
    'lipnc#xoP34?Uf8}Zm6mwSQyI5x;#eCEj>Ad~RJisoXvSbDee-Ta;%R85wwE$D|vDq9ldh3Wgo'
    'MKz~QnxWQw4+8RhUQ?4nz~7lc{t3OsZZuaAi+|~1+T`|*cIKK|1R*ta4l&^!gs2Xmi)s!okGWd'
    'p%3&zW4Jmf9fs3R8D`f-;kB7NhP30Dl9q5owpTbS8)mqqaM(o}Inh5E4AQu+7vs9q|q)BxP+H-'
    'S>PZ8>7g$8Z`SL92J2OEB0g4VwXE)fKIz`M^Cti~2dryHY5?>hV#hc%<p_GD<Q-WV()e4vG(O*'
    '{+_6iU>{H5r8|bol!cHhydR<G_nx3n>%^5!rz_u*S`B$Sw1jCb`{^TNO4T#C=|a4V+`KnsYil>'
    '`5vu15CIgf1w;|K^){}9MmwO?uL0kc6=50Hf!F*x46GamP!F<_-@5|xJi7=1G%H423n-11!1_W'
    '#6iL_GD)cGf{-pWslNc?Kqm1pY?Q;I#hwy79Sh4L2x}Ll32l;Yk<M^E%WL6yASSYx_hXC3jE$n'
    'Ah<pffEfJPX*qUpqIq)2f_$EtVqj}4l)s6&W2SA8_`9_4;Y2t{-(K5xpBfCY|ILz49g?okNf!N'
    '0ZS@C8TxX(?#V1Rpw0~;r3P3%=TS~l2H6_<+w@y3RZgB5NeGf1}&#*<wj5Z=>^HH1Yx4s&|TLb'
    'r%K%wE%hFsVhWK=95W|I+Y|Ejm;d3w>V;nL)-lud@?`O;dCUw0K84Y-3@;4K>6@7e$)#GZN$h`'
    'n$g7dZ63FZuKHTsQEnva+3%$t+N4H0&g?2;N6QnZbdH8QbHM3n~j>P5-j)IPvm{nc49d9EtxH<'
    'Y4l$tNY@4FC)7ooqs?@&u=qw|fp#1ZvTGBby=V}akZ=A_XU}T)Q-=-V+I^M-H}m_2wIW@zw4r4'
    '#YiNj<AgzW8u7%@0VL?POP@Cdiqr=@o{)yRU?#IH8Lp`Iuy5JjLlWq=44a;|s)tWfnZqhzjTDZ'
    '_Gb%2m=j|A!54*U2GcGAhVhzGvDlmlPuJ@`LEcXI-XawGbA4cS+$z7+m;dXg~xCcebdf|Kd5SN'
    'to}ZqiN*hrrVUA@8;#Ksx>8YARj#o|O8NEs{xpS0y#L;dmk%_In;ox7Q!;uF`mtAPndFdOS?QK'
    '!lFjhyG8QU!~N`?u%aZqNC`49-Llwt;ZUX0000bbVXQnWMOn=I%9HWVRU5xGB7bYEio`HFg8>%'
    'H99jmIxsXVFfckWFdV)gE&u=kC3HntbYx+4WjbwdWNBu305UK!GA%GSEiyM$GBG+ZHaapiD=;u'
    'RFfhRbg9`uv02y>eSaefwW^{L9a%BK_cXuvnZfkR6VQ^(GZ*pgw?mQX*0000<MNUMnLSTX'
)

This fragment can be included in a Python script. That script should also import base64. When the aforementioned script is run, data references the content of the original file.

In case this is compressed data you will have to add the decompression step yourself.


←  ImageMagick: convert vs Wand How convenient is multithreading compared to multiprocessing?  →