Fetching BLOB from Mysql db and load into recycleview

287 views
Skip to first unread message

Poorya bolooryan

unread,
Jun 18, 2020, 10:54:15 AM6/18/20
to Kivy users support
Dears,
i already imported texts from mysql db but when i reached to BLOB types i have problem which give me following error:

***** ValueError: ImageAndTitle.source accept only str *****

the method im using is to def a write_file method and read_blob method:

which i inserted here :
Main.py file:
class TestBox(BoxLayout):
data_items = ListProperty()
images = ListProperty()
def __init__(self, **kwargs):
super(TestBox, self).__init__(**kwargs)
self.get_users()


def get_users(self):
connection = mysql.connector.connect(user="*****", password="******", database="*****")
cursor = connection.cursor()

query =("SELECT servicename_ku FROM service_cat ORDER BY service_id ASC")
cursor.execute(query)
rows = cursor.fetchall()

# create data_items like a list to read each title
for row in rows:
for col in row:
self.data_items.append(col)
print(self.data_items)

def write_file(data, filename):
with open(filename, 'wb') as f:
f.write(data)

def get_img(self):
query1 =("SELECT service_img FROM service_cat ORDER BY service_id ASC")
cursor.execute(query1)
images = cursor.fetchall()
weite_file(images, filename)
print(images)






###my Kv file attached here:

<TestBox>:
#set and Arrange the Recycleview features
RecycleView:
id: rv
viewclass:'ImageAndTitle'
bar_width: 2
effect_cls: ScrollEffect
# n is each one of words in data_image list
# root is look at TestBox in this code
data: [{'source': root.images, 'title': get_display(arabic_reshaper.reshape(n))} for n in root.data_items]
RecycleBoxLayout:
default_size: dp(170), dp(153)
default_size_hint: None, None
size_hint: None, None
width: self.minimum_width
height: self.minimum_height
orientation: 'horizontal'
padding: 9
spacing: 20

how i should add images from DB to the recycleview ???

Elliot Garbus

unread,
Jun 18, 2020, 11:38:51 AM6/18/20
to kivy-...@googlegroups.com

Here is at least one issue:

        data: [{'source': root.images, 'title': get_display(arabic_reshaper.reshape(n))} for n in root.data_items]

 

You are setting source to the entire list root.images.  I assume the images list is a list of filenames.

If so you want something like:

data: [{'source': root.images[i], 'title': get_display(arabic_reshaper.reshape(n))} for i, n in enumerate(root.data_items)]

--
You received this message because you are subscribed to the Google Groups "Kivy users support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/7c45aecd-9489-48dc-8d75-c798f7f4f67fo%40googlegroups.com.

 

Poorya bolooryan

unread,
Jun 20, 2020, 9:17:27 AM6/20/20
to Kivy users support
now after working on it change from mysql connection to pymysql and separation of columns i reached to this point with this error:
      45:    RecycleView:
      46:        #data: [{'source': [n]} for n in root.images]
 >>   47:        data : [{'source': [i], 'title': get_display(arabic_reshaper.reshape(n))} for i,n in enumerate(root.images,root.data_items)]
      48:        id: rv
      49:        viewclass:'ImageAndTitle'
 TypeError: 'ObservableList' object cannot be interpreted as an integer

Main.py
class TestBox(BoxLayout):

data_items = ListProperty()
images = ListProperty()
    titles_eng = ListProperty()


def __init__(self, **kwargs):
super(TestBox, self).__init__(**kwargs)
self.get_users()


    def write_file(data, filename):
with open(filename, 'wb') as f:
f.write(data)

    def get_users(self):
connection = pymysql.connect(user='****', password= '******', database='****')
cursor = connection.cursor()

cursor.execute("SELECT servicename_ku, service_img, servicename FROM service_cat ORDER BY service_id ASC")

rows = cursor.fetchall()
# create data_items
        for row in rows:
title = row[0]
image = row[1]
t_eng = row[2]
self.data_items.append(title)
self.images.append(image)
self.titles_eng.append(t_eng)


slide.kv

<TestBox>:
#set and Arrange the Recycleview features
RecycleView:
        #data: [{'source': [n]} for n in root.images]
data : [{'source': [i], 'title': get_display(arabic_reshaper.reshape(n))} for i,n in enumerate(root.images,root.data_items)]

id: rv
viewclass:'ImageAndTitle'
bar_width: 2
effect_cls: ScrollEffect
        RecycleBoxLayout:
default_size: dp(170), dp(153)
default_size_hint: None, None
size_hint: None, None
width: self.minimum_width
height: self.minimum_height
orientation: 'horizontal'
padding: 9
spacing: 20

i used write_method and i can export image to the folder,now its my concern how to use image blob file directly inside recycleview.

 ...

To unsubscribe from this group and stop receiving emails from it, send an email to kivy-...@googlegroups.com.

Elliot Garbus

unread,
Jun 20, 2020, 10:33:12 AM6/20/20
to kivy-...@googlegroups.com

[{'source': [i], 'title': get_display(arabic_reshaper.reshape(n))} for i,n in enumerate(root.images,root.data_items)]

The line above a valid Python statement.  Example:

>>> a

['A0', 'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9']

>>> b

['B0', 'B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B9']

>>> for i, d in enumerate(b):

       print(f'i: {i}, a[i]: {a[i]}, d: {d}')

 

      

i: 0, a[i]: A0, d: B0

i: 1, a[i]: A1, d: B1

i: 2, a[i]: A2, d: B2

i: 3, a[i]: A3, d: B3

i: 4, a[i]: A4, d: B4

i: 5, a[i]: A5, d: B5

i: 6, a[i]: A6, d: B6

i: 7, a[i]: A7, d: B7

i: 8, a[i]: A8, d: B8

i: 9, a[i]: A9, d: B9

>>> 

 

You could say:

[{'source': root.images[i], 'title': get_display(arabic_reshaper.reshape(data_item))} for i, data_item in enumerate(root.data_items)]

To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/4adc96e7-8725-42c5-90b9-b90047c6d70do%40googlegroups.com.

 

Poorya bolooryan

unread,
Jun 20, 2020, 10:54:05 AM6/20/20
to Kivy users support
Traceback (most recent call last):
   File "kivy\properties.pyx", line 599, in kivy.properties.Property.dispatch
   File "kivy\_event.pyx", line 1214, in kivy._event.EventObservers.dispatch
   File "kivy\_event.pyx", line 1096, in kivy._event.EventObservers._dispatch
   File "D:\Python\Spana\venv\lib\site-packages\kivy\lang\builder.py", line 73, in call_fn
     e_value = eval(value, idmap)
   File "D:\Python\Spana\venv\kv\sliding.kv", line 48, in <module>
     data : [{'source': root.images[i], 'title': get_display(arabic_reshaper.reshape(data_item))} for i, data_item in enumerate(root.data_items)]
   File "D:\Python\Spana\venv\kv\sliding.kv", line 48, in <listcomp>
     data : [{'source': root.images[i], 'title': get_display(arabic_reshaper.reshape(data_item))} for i, data_item in enumerate(root.data_items)]
 IndexError: list index out of range
[INFO   ] [Base        ] Start application main loop
[INFO   ] [Base        ] Leaving application in progress...
 Traceback (most recent call last):
   File "D:/Python/Spana/venv/main.py", line 211, in <module>
     MainApp().run()
   File "D:\Python\Spana\venv\lib\site-packages\kivy\app.py", line 855, in run
     runTouchApp()
   File "D:\Python\Spana\venv\lib\site-packages\kivy\base.py", line 504, in runTouchApp
     EventLoop.window.mainloop()
   File "D:\Python\Spana\venv\lib\site-packages\kivy\core\window\window_sdl2.py", line 747, in mainloop
     self._mainloop()
   File "D:\Python\Spana\venv\lib\site-packages\kivy\core\window\window_sdl2.py", line 479, in _mainloop
     EventLoop.idle()
   File "D:\Python\Spana\venv\lib\site-packages\kivy\base.py", line 339, in idle
     Clock.tick()
   File "D:\Python\Spana\venv\lib\site-packages\kivy\clock.py", line 591, in tick
     self._process_events()
   File "kivy\_clock.pyx", line 384, in kivy._clock.CyClockBase._process_events
   File "kivy\_clock.pyx", line 414, in kivy._clock.CyClockBase._process_events
   File "kivy\_clock.pyx", line 412, in kivy._clock.CyClockBase._process_events
   File "kivy\_clock.pyx", line 167, in kivy._clock.ClockEvent.tick
   File "D:\Python\Spana\venv\lib\site-packages\kivy\uix\recycleview\__init__.py", line 257, in refresh_views
     lm.set_visible_views(indices, data, viewport)
   File "D:\Python\Spana\venv\lib\site-packages\kivy\uix\recyclelayout.py", line 236, in set_visible_views
     indices, data, view_opts)
   File "D:\Python\Spana\venv\lib\site-packages\kivy\uix\recycleview\views.py", line 366, in set_visible_views
     viewclasses[index]['viewclass'])
   File "D:\Python\Spana\venv\lib\site-packages\kivy\uix\recycleview\views.py", line 221, in get_view
     view = self.create_view(index, data_item, viewclass)
   File "D:\Python\Spana\venv\lib\site-packages\kivy\uix\recycleview\views.py", line 185, in create_view
     self.refresh_view_attrs(index, data_item, view)
   File "D:\Python\Spana\venv\lib\site-packages\kivy\uix\recycleview\views.py", line 250, in refresh_view_attrs
     setattr(view, key, value)
   File "kivy\properties.pyx", line 497, in kivy.properties.Property.__set__
   File "kivy\properties.pyx", line 541, in kivy.properties.Property.set
   File "kivy\properties.pyx", line 532, in kivy.properties.Property.set
   File "kivy\properties.pyx", line 698, in kivy.properties.StringProperty.check
 ValueError: ImageAndTitle.source accept only str


i used this method before and got above error, blob files should be first converted to readable type and shall be loaded to the memory then Image in kivy that loaded file this is what i can not understand.

Elliot Garbus

unread,
Jun 20, 2020, 11:09:08 AM6/20/20
to kivy-...@googlegroups.com

I see 2 errors below:

IndexError: list index out of range

It appears there are not the same number of items in root.data_items and root.images.  Is this correct?

 

 ValueError: ImageAndTitle.source accept only str

What is the content of root.images[i] ?

 

If you print(type(root.images[0]) what is printed?

To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/c8dea2e3-2de3-4c3b-93ad-c124999aa8f8o%40googlegroups.com.

 

Poorya bolooryan

unread,
Jun 20, 2020, 11:19:30 AM6/20/20
to Kivy users support
  def get_users(self):
connection = pymysql.connect(user='****', password= '******', database='****')
cursor = connection.cursor()

cursor.execute("SELECT servicename_ku, service_img, servicename FROM service_cat ORDER BY service_id ASC")

rows = cursor.fetchall()
# create data_items
for row in rows:
title = row[0]
image = row[1]
t_eng = row[2]
self.data_items.append(title)
self.images.append(image)
self.titles_eng.append(t_eng)
 both root.data_items and root.imges are in the same table inside DB so thier index which is follow service_id should be same.

root images is ListProperty which is include blob images from data base as it mentioned in the code above.

On Saturday, June 20, 2020 at 7:39:08 PM UTC+4:30, Elliot Garbus wrote:

I see 2 errors below:

IndexError: list index out of range

It appears there are not the same number of items in root.data_items and root.images.  Is this correct?

 

 ValueError: ImageAndTitle.source accept only str

What is the content of root.images[i] ?

 

If you print(type(root.images[0]) what is printed?

 

 if i print root.images in kv file will give me again the :     IndexError: list index out of range

Poorya bolooryan

unread,
Jun 20, 2020, 11:32:49 AM6/20/20
to Kivy users support
Dear Elliot if you agree lets see this code i wrote it here:

in mentioned code everything is working i can get title and title_english correctly.
i can read the blob file from mysql as well and when run the code one image from database will stored in mentioned address i gave.
now my challenge is to know how should i set the title with image in recycleview(probably with enumerate()). lets say how to send my loaded image from database directly to the recycleview without store in hard drive?


here is my code which is absolutely functional
import mysql.connector
import pymysql
from kivy.app import App

class TextBox():

def __init__(self, **kwargs):
super(TestBox, self).__init__(**kwargs)
        self.write_file()

def write_file(data, filename):
with open(filename, 'wb') as file:
file.write(data)

def get_img(service_id, filename):
connection = pymysql.connect(user="****", password="******", database="*****")
cursor = connection.cursor()
query1 =("SELECT service_img, servicename_ku, servicename FROM service_cat WHERE service_id = %s")
cursor.execute(query1, (service_id,))
records = cursor.fetchall()
for field in records:
image = field[0]
title = field[1]
english_title = field[2]
TextBox.write_file(image, filename)
print(title)

class MainApp(App):

TextBox.get_img(4, "D:\Python\spana\example.png")
MainApp().run()

Elliot Garbus

unread,
Jun 20, 2020, 12:23:40 PM6/20/20
to kivy-...@googlegroups.com

Please attach a more complete section of code. 

As I understand it.  You are pulling images from the database, and writing them to files.  The filenames are being stored in a list, images. 

 

Print the len(root.images) and print(len(root.data_items)) are they the same?

Print root.images  is it the expected list of filenames?

To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/ccf65b25-c728-454c-baa0-f13797d2e7e0o%40googlegroups.com.

 

Poorya bolooryan

unread,
Jun 21, 2020, 3:13:59 AM6/21/20
to Kivy users support
what i am looking for is to use Blob data from Mysql directly inside recycleview without save file in hard drive.
i searched and found io built-in module ByteIO or StringIO, now i need to add it in my code 
no the length of root.image with root.data_items are not the same and should not be because root.image include image but roo.data_items include text.

there is no file name in expected list.

i believe i should use IO built-in module in my code.
Message has been deleted

Poorya bolooryan

unread,
Jun 21, 2020, 8:51:30 AM6/21/20
to Kivy users support
Dear Elliot,
i already got the output from BLOB data (first Blob data in Python is Bytes and then i used PIL to see the image which was correct output)
the problem is Image.source only accept string value then its a question how to convert this type of data to the readable format for Image?
I believe that using StringIO is not a good idea because source of image essentially looking for place of image (please correct me if im wrong).
i will add my final code with all details here please have look and let me know how i should do this .appreciate alot for your kind help.


note that when i run my code below i receive such a error :

 BuilderException: Parser: File "D:\Python\Spana\venv\kv\sliding.kv", line 48:
 ...
      46:        #data : [{'source': [i], 'title': root.data_items(get_display(arabic_reshaper.reshape(n)))} for i,n in enumerate(root.images)]
      47:        #'title': (get_display(arabic_reshaper.reshape(n)))} for n in root.txt
 >>   48:        data : [ {'source': root.images2[i]} for i in range(6)]
      49:        id: rv
      50:        viewclass:'ImageAndTitle'
 ...
 IndexError: list index out of range
   File "***********\venv\lib\site-packages\kivy\lang\builder.py", line 249, in create_handler
     return eval(value, idmap), bound_list
   File "***************\venv\kv\sliding.kv", line 48, in <module>
     data : [ {'source': root.images2[i]} for i in range(6)]
   File "***********\venv\kv\sliding.kv", line 48, in <listcomp>
     data : [ {'source': root.images2[i]} for i in range(6)]
 
   File "**************\venv\lib\site-packages\kivy\lang\builder.py", line 692, in _apply_rule
     rctx['ids'])
   File "************venv\lib\site-packages\kivy\lang\builder.py", line 254, in create_handler
     cause=tb)

if i remove the loop and run the code again its okay and everything working properly and its the output of prints:

<class 'tuple'> this tuple refer to records in my code
<class 'bytes'> these bytes are my images
پاک کردنەوە           these are texts 
<class 'bytes'>
دیکۆراتی مال
<class 'bytes'>
گۆاستنەوە
<class 'bytes'>
خەدەماتی ئۆتۆمبیل
<class 'bytes'>
خەدەماتی بینا
<class 'bytes'>
کەلوپەلی ناومال
<class 'bytes'>
دیجیتال

main.py



class ImageAndTitle(MDBoxLayout, ButtonBehavior):
source = StringProperty()
title = StringProperty()


class TestBox(BoxLayout):
txt = ListProperty()
images2 = ListProperty()
records = ListProperty()

def __init__(self, **kwargs):
super(TestBox, self).__init__(**kwargs)
        self.get_cat()

def get_cat(self):
connection = pymysql.connect(user="*****", password="*******", database="******")
cursor = connection.cursor()
query1 =("SELECT service_img,servicename_ku,servicename FROM service_cat ORDER BY service_id")
cursor.execute(query1)
records = cursor.fetchall()
file1 = BytesIO(records[0][0])
img1 = PIL.Image.open(file1)
self.images2.append(img1)
print(type(records[0]))
for field in records:
tex = field[1]
img = field[0]
print(type(img))
print(tex)
self.txt.append(tex)








kv file 



#:import utils kivy.utils
#:import SmartTileWithLabel kivymd.uix.imagelist.SmartTileWithLabel
#:import ScrollEffect kivy.effects.scroll.ScrollEffect
#:import ScrollEffect kivy.effects.scroll.ScrollEffect
#:import get_display bidi.algorithm.get_display
#:import arabic_reshaper arabic_reshaper

<ImageAndTitle>:
#produce the MDCard Material Icons
MDCard:
orientation: "vertical"
border_radius : "20dp"
radius : [10]
focus_behavior: False
elevation: 1
spacing: 10
padding: [0,20,0,20]
md_bg_color: utils.get_color_from_hex("#fcfcfc")
Image:
source: root.source
size_hint_y: self.size_hint_min_y
MDLabel:
text: root.title
halign: "center"
theme_text_color: "Primary"
font_style: "Subtitle1"



<TestBox>:
#set and Arrange the Recycleview features
RecycleView:
#data: [{'source': [n]} for n in root.images]
        #data : [{'source': [i], 'title': root.data_items(get_display(arabic_reshaper.reshape(n)))} for i,n in enumerate(root.images)]
#[
'title': (get_display(arabic_reshaper.reshape(n)))} for n in root.txt ] 

         above for loop is working for title and i can get text from DB my problem is with Blob Data

data : [ {'source': root.images2[i]} for i in range(7)]

id: rv
viewclass:'ImageAndTitle'
bar_width: 2
effect_cls: ScrollEffect
RecycleBoxLayout:
default_size: dp(170), dp(153)
default_size_hint: None, None
size_hint: None, None
width: self.minimum_width
height: self.minimum_height
orientation: 'horizontal'
padding: 9
spacing: 20

thanks for your help

Elliot Garbus

unread,
Jun 21, 2020, 9:35:30 AM6/21/20
to kivy-...@googlegroups.com

To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/bb618036-fc0d-41f9-9862-a1fc2d10e245o%40googlegroups.com.

 

Poorya bolooryan

unread,
Jun 23, 2020, 6:43:36 AM6/23/20
to Kivy users support
My problem solved by use BytesIO to convert binary to bytes and then using CoreImage and then Texture.
if we want to address the Texture Image in Kivy Lang we should using texture: instead of source: for Image.
Thank you Elliot for your help.
Reply all
Reply to author
Forward
0 new messages