How to display a BLOB object (image) from sqlite3 with Python - python

I saved an image as a BLOB in a sqlite3 database column profile - I summon the function insertBLOB with relevant info:
sqliteConnection = sqlite3.connect('image_try.db')
cursor = sqliteConnection.cursor()
cursor.execute("""CREATE TABLE IF NOT EXISTS images (
id INTEGER PRIMARY KEY,
fullname TEXT,
username TEXT,
profile BLOB)""")
def convertToBinaryData(filename):
with open(filename, 'rb') as file:
blobData = file.read()
return blobData
def insertBLOB(name, username, photo):
sqliteConnection = sqlite3.connect('image_try.db')
sqliteConnection.text_factory = str
cursor = sqliteConnection.cursor()
sqlite_insert_blob_query = """ INSERT INTO images
(fullname, username, profile) VALUES (?, ?, ?)"""
empPhoto = convertToBinaryData(photo)
data_tuple = (name, username, empPhoto)
cursor.execute(sqlite_insert_blob_query, data_tuple)
sqliteConnection.commit()
I tried to access the image file (so I could display it in a Label) like this - by summoning the function readBlobData:
def writeTofile(data):
# Convert binary data to proper format and write it on Hard Disk
this = open(data, 'rb')
this.open(io.BytesIO(base64.b64decode(data)))
return this
def readBlobData(empId):
try:
sqliteConnection = sqlite3.connect('image_try.db')
sqliteConnection.text_factory = str
cursor = sqliteConnection.cursor()
sql_fetch_blob_query = """SELECT * from images where id = ?"""
cursor.execute(sql_fetch_blob_query, (empId,))
record = cursor.fetchall()
profile = record[0][3] #Blob object
profile = writeTofile(profile)
image = ImageTk.PhotoImage(profile)
image_label = Label(root, image=image)
image_label.photo = image
image_label.pack()
cursor.close()
when I summon the function readBlobData I get this Error:
Traceback (most recent call last):
File "C:/Users/hilab/PycharmProjects/dafyProject/addimage.py", line 90, in
<module>
readBlobData(1)
File "C:/Users/hilab/PycharmProjects/dafyProject/addimage.py", line 67, in
readBlobData
profile = writeTofile(profile)
File "C:/Users/hilab/PycharmProjects/dafyProject/addimage.py", line 51, in
writeTofile
this = open(data, 'rb')
TypeError: file() argument 1 must be encoded string without NULL bytes, not str
Do you have any idea what seems to be the problem? and how can I fix it? How can I access the BLOB object from the SQLite database and present it???

The traceback is telling us that something is going wrong in the writeToFile function, specifically when we try to open a file:
profile = writeTofile(profile)
File "C:/Users/hilab/PycharmProjects/dafyProject/addimage.py", line 51, in
writeTofile
this = open(data, 'rb')
TypeError: file() argument 1 must be encoded string without NULL bytes, not str
The value that we are passing to the function is the binary image data read from the database
profile = record[0][3]
In the function, we are trying to use this binary data as the name of the file that we are going to read from to get the binary data in some format.
def writeTofile(data):
# Convert binary data to proper format and write it on Hard Disk
this = open(data, 'rb')
this.open(io.BytesIO(base64.b64decode(data)))
return this
tkinter.PhotoImage expects the path to a file, according to its documentation, so we have to create a file from the image bytes.:
def writeTofile(data):
# Write it to the Hard Disk
# (ideally with a suitable name and extension)
filename = 'myfile.img'
with open('myfile.img', 'wb') as f:
f.write(data)
return filename
And in readBlobData:
image = ImageTk.PhotoImage(file=profile)
And then all should be well.

Related

i get this Error: expected str, bytes or os.PathLike object, not File when call file on db

i made sqlalchemy db and upload cs file.
but when i try to call fie that inside the db its alwayd show this error
Error: expected str, bytes or os.PathLike object, not File
is there any option to change file query into file path?
if i change with open(my_data, newline='') as f:
to
with open("augut.csv", newline='') as f: its work. but i want to call file that already store in db.
'''
#app.route("/proses/<id>/", methods=["GET"])
def proses(id):
my_data = File.query.get(id)
with open(my_data, newline='') as f:
reader = csv.reader(f)
data = list(reader)
transactions = data
patterns = pyfpgrowth.find_frequent_patterns(transactions, len(transactions) * 20/100)
rules = pyfpgrowth.generate_association_rules(patterns, 0.5)
return str(rules)
'''
The call to File.query.get(id) return a File instance. You need to get the file name from my_data and use it with open
Assuming you have something like:
class File(Base):
__tablename__ = 'some_table'
id = Column(Integer, primary_key=True)
name = Column(String(50))
the call to my_data.name will return the file name

How to fix Unable to upload file. TypeError("a bytes-like object is required, not 'str'",) when trying to upload a csv file

Why i got the error of Unable to upload file. TypeError("a bytes-like object is required, not 'str'",) when trying to upload a .csv file in order to update the value of my model fields?
The first line of my .csv file has the sku of the products , which is CharField field in my model
The second line of my .csv file has the quantity of the products , which is DecimalField field in my model.
Here is my code:
def upload_massive_skus_and_quantities(request):
#list_with_not_uploaded_skus=[]
sum_updated=0
sum_created=0
total=0
data = {}
if "GET" == request.method:
return render(request, "csv/upload2_csv.html", data)
# if not GET, then proceed
try:
csv_file = request.FILES["csv_file"]
if not csv_file.name.endswith('.csv'):
messages.error(request,'File is not CSV type')
return HttpResponseRedirect(reverse("upload_massive_skus_and_quantities"))
#if file is too large, return
if csv_file.multiple_chunks():
messages.error(request,"Uploaded file is too big (%.2f MB)." % (csv_file.size/(1000*1000),))
return HttpResponseRedirect(reverse("upload_massive_skus_and_quantities"))
file_data = csv_file.read()
lines = file_data.split("\n")
#loop over the lines and save them in db. If error , store as string and then display
for line in lines:
fields = line.split(";")
sku_field=fields[0] #take the sku
quantity_field=fields[1] #take the quantity
fetched_product=Product.objects.get(code=sku_field)
try:
#update
fetched_warehouse_product=Warehouse_Has_Products.objects.get(warehouse_id=12,warehouse_product_id=fetched_product.id)
fetched_warehouse_product.quantity=Decimal(quantity_field)
fetched_warehouse_product.save()
sum_updated+=1
total+=1
except:
#create
Warehouse_Has_Products.objects.create(warehouse_id=12,warehouse_product_id=fetched_product.id,quantity=Decimal(quantity_field))
sum_created+=1
total+=1
except Exception as e:
logging.getLogger("error_logger").error("Unable to upload file. "+repr(e))
messages.error(request,"Unable to upload file. "+repr(e))
return HttpResponseRedirect(reverse("upload_massive_skus_and_quantities"))
The error i think raises from the line : file_data = csv_file.read()
Any idea how to fix this?

Store Gtk.Textbuffer in SQL database. Encoding troubles

I'm working on a note taking app using python2/Gtk3/Glade.
The notes are stored in a MySQL Database and displayed in a TextView widget.
I can load/store/display plain text fine. However I want the ability to add images to the note page, and store them in the Database.so the data has to be serialised and I'm having some trouble figuring out how to encode/decode the serialised data going in and out of the Database. I'm getting unicode start byte errors. If was working with files I could just open the file in binary mode, but I'm storing as a string in a Database. I've tried encoding/decoding as UTF-8 and ASCII using bytes() and string.encode()[see the sample code below] and a few other ways but none work.
I am using this function to add the image to the textview buffer:
def _AddImagetoNode(self,oWidget):
filenm = None
seliter = self.GetTreeSelection(self.treeview)
filenm = self.FileOpenDiag("Select an Image To Insert.","Image","*.png,*.jpg,*.bmp")
if filenm == None:
return()
#filenm = "/home/drift/Pictures/a.png"
buf = self.dataview.get_buffer()
pixbuf = GdkPixbuf.Pixbuf.new_from_file(filenm)
#pixbuf.scale_simple(dest_width, dest_height, gtk.gdk.INTERP_BILINEAR)
buf.insert_pixbuf(buf.get_end_iter(), pixbuf)
self.dataview.set_buffer(buf)
self.dataview.show()
This is the function that stores the textview buffer:
def SaveDataView(self):
global DataViewNode
global DataViewIsImage
if len(self.GetProjectName()) == 0:
return()
buf = self.dataview.get_buffer()
format = buf.register_serialize_tagset()
data2 = buf.serialize(buf, format, buf.get_start_iter(), buf.get_end_iter())
#convert bytes(data) to string
data = data2.decode(encoding='UTF-8') #<< i think my problem is here
print("save b4 decode >>>>>>:%s"%data2)
sql = "UPDATE " + self.GetProjectName() + " SET tDataPath=%s WHERE tNodeID=%s"
val = (data, DataViewNode)
self.cursor.execute(sql,val)
self.mariadb_connection.commit()
This is the function that loads the Buffer:
def UpdateDataView(self, nodeid):
global DataViewNode
#global DataViewIsFile
DataViewNode=nodeid
if self.GetProjectName() != None and DataViewNode != None:
self.dataview.set_sensitive(True)
else:
self.dataview.set_sensitive(False)
self.dataview.show()
return()
buf = self.dataview.get_buffer()
buf.set_text('')
enc = self.DbGetNodeData(nodeid)
#convert string(enc) to bytes
data = enc.encode(encoding='UTF-8')#<<< i think my problem is here
print("update after decode >>>>>>>>>: %s"%data)
########### load
format = buf.register_deserialize_tagset()
buf.deserialize(buf, format, buf.get_end_iter(),data)
#buf.set_text(enc)
self.dataview.set_buffer(buf)
self.dataview.show()
I'm using mysql.connector to connect to a mariadb.
This is the sql connection string:
self.mariadb_connection = mariadb.connect(user='box', password='box', host='localhost', database='Boxer',charset='utf8')
This is the error im getting.
Traceback (most recent call last): File "Boxer.py", line 402, in
_TreeSelectionChanged
self.SaveDataView() File "Boxer.py", line 334, in SaveDataView
data = data2.decode(encoding='UTF-8') UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb4 in position 174: invalid start byte
Traceback (most recent call last): File "Boxer.py", line 398, in
_DataViewLostFocus
self.SaveDataView() File "Boxer.py", line 334, in SaveDataView
data = data2.decode(encoding='UTF-8') UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb4 in position 174: invalid start byte
With this code I can add/edit plain text in the text view and successfully save/load it but as soon as I add the image, I'm get the encoding errors. Any help would be appreciated.
Here is a more complete example:
def example (self):
#retrieve info from first textview
buf = self.builder.get_object('textbuffer1')
format = buf.register_serialize_tagset()
data = buf.serialize(buf, format, buf.get_start_iter(), buf.get_end_iter())
#run db update to prove it can be inserted into a database
db = psycopg2.connect(database= 'silrep_restore3', host='192.168.0.101',
user='postgres', password = 'true',
port = '5432')
c = db.cursor()
c.execute("UPDATE products SET byt = %s WHERE id = 1", (psycopg2.Binary(data),))
#append info to second treeview as a proof of concept
c.execute("SELECT byt FROM products WHERE id = 1")
data = c.fetchone()[0]
buf = self.builder.get_object('textbuffer2')
format = buf.register_deserialize_tagset()
buf.deserialize(buf, format, buf.get_end_iter(), data)
Since you are using MySQL, I recommend reading this article about inserting and retrieving data like you are.
For my example I used a bytea column. In MySQL this is may be a BLOB or BINARY type.
P.S. Sorry for not having a complete MySQL example in my answer. I would have posted a comment, but comments are pathetic for proper formatting.
Got it workings. thanks to theGtknerd your answer was the key. for anyone else having trouble with this i ended up using the BLOB type for the MySQL field type for the column im working with. I tried BINARY[it returnd malformed serialize data] AND VARBINARY [wouldnt even allow me to create the table] so i ended up using the LONGBLOB type.
here is the working code for anyone that needs it.
def UpdateDataView(self, nodeid):
global DataViewNode
#global DataViewIsFile
DataViewNode=nodeid
if self.GetProjectName() != None and DataViewNode != None:
self.dataview.set_sensitive(True)
else:
self.dataview.set_sensitive(False)
self.dataview.show()
return()
buf = self.dataview.get_buffer()
buf.set_text('')
data = self.DbGetNodeData(nodeid)
if data =='':
return()
format = buf.register_deserialize_tagset()
buf.deserialize(buf, format, buf.get_end_iter(),data)
self.dataview.set_buffer(buf)
self.dataview.show()
def SaveDataView(self):
global DataViewNode
global DataViewIsImage
if len(self.GetProjectName()) == 0:
return()
buf = self.dataview.get_buffer()
enc = buf.get_text(buf.get_start_iter(),buf.get_end_iter(),False)
self.AddData2Db(DataViewNode,enc)
format = buf.register_serialize_tagset()
data = buf.serialize(buf, format, buf.get_start_iter(), buf.get_end_iter())
sql = "UPDATE " + self.GetProjectName() + " SET tDataPath=%s WHERE tNodeID=%s"
val = (data, DataViewNode)
self.cursor.execute(sql,val)
self.mariadb_connection.commit()
and im using this to create the table
sql = "CREATE TABLE %s (tParentNodeID TEXT,tNodeTxt TEXT,tNodeID TEXT,tDataPath LONGBLOB)" %pName
self.cursor.execute(sql)
self.mariadb_connection.commit()

why there is error on cancel qfiledialog?

That is my code
def report_one_friend(self):
filename = QFileDialog.getSaveFileName(self, "", "cars.xlsx","Excel(.xlsx)")
if filename:
openFile = open(filename, 'r').read()
self.plainTextEdit.appendPlainText(openFile)
wb = xlsxwriter.Workbook(filename[0])
sheet1 = wb.add_worksheet()
sql = '''SELECT * FROM ahmed WHERE mth_search = %s'''
mth_search = self.lineEdit_3.text()
c = self.conn.cursor()
c.execute(sql, [(mth_search)])
data = c.fetchall()
for row in data:
print(row)
sheet1.write(0,2,'الاسم')
sheet1.write(0,0,row[1])
sheet1.write(1, 2, 'الرقم')
sheet1.write(1, 0, row[2])
wb.close()
and that gives me an error :
Connected to MySQL database using C extension... MySQL Server version on 8.0.12
Traceback (most recent call last):
File "/Users/mahmoudtarek/Desktop/mth1/index.py", line 174, in mth_friends
self.report_one_friend()
File "/Users/mahmoudtarek/Desktop/mth1/index.py", line 208, in report_one_friend
openFile = open(filename, 'r').read()
TypeError: expected str, bytes or os.PathLike object, not tuple
you get a tuple of "the selected file" and "the applied filter".
minimal code example:
from PyQt5.Qt import *
app = QApplication([])
print(QFileDialog.getSaveFileName())
selected "some file":
('C:/scratches/scratch.py', 'All Files (*)')
But when you dont select something and cancel the dialog, then the two strings are empty: ('', '').
Because a tuple with two strings in it is true, you try to open() a file with this, which leads to you error.
Solution:
unpack the tuple into two variables or use index[0] like in the following:
filename, filter = QFileDialog.getSaveFileName(self, "", "cars.xlsx","Excel(.xlsx)")
if filename:
openFile = open(filename, 'r').read()
...

Odoo8.0, cannot valid the csv file when try to import it

I have problem when i was try to import .csv file. I was try to convert image to base64 and also i was try to create barcode by name csv file. The image it's success convert into base64 but the problem when i was try to create barcode by csv file name, i was always get error like :
Unknown error during import: <class 'openerp.exceptions.ValidationError'>: ('ValidateError', u'Field(s) `ean13` failed against a constraint: You provided an invalid "EAN13 Barcode" reference. You may use the "Internal Reference" field instead.') at row 2 Resolve other errors first
And this is my code:
files = []
text = ''"
data_text3 = []
header_column2 = ["id","product_variant_ids/ean13_barcode", "product_variant_ids/ean13", "ean13", "image", "ean13_barcode", "default_code", "product_variant_ids/default_code"]
number = 1 for file in os.listdir("gmbr/"):
file_name = os.path.splitext(file)[0]
for n in str(number):
directory_file = "gmbr/"+str(file)
img = open(directory_file, 'rb').read()
img_64 = base64.encodestr
text = str(number)+","+str(name_product)+","+str(file_name)+","+str(file_name)+","+str(img_64+","+" "+","+" "+","+" ")
number += 1
data_text3.append(text)
with open('sample2.csv', 'wb') as f:
writer = csv.writer(f, delimiter='\t', dialect='excel')
writer.writerow(header_column2)
for l in data_text3:
writer.writerow(l.split(','))

Categories