Please step by step guide How to create snap and YAML for python tkinter app READING INTERNAL FILESYSTEM OF SNAP WITH TKINTER. THANKS A LOT :)

Ok, I have python app where I have used tkinter, this app reads /data/pictures.jpg and /data/questions.txt I do not know how to create *.snap file. I read the docs, the tuts, but nothing worked for me. My glued yaml is this probably WRONG piece:

    name: autoskola-free8 # you probably want to 'snapcraft register <name>'
    version: '8' # just for humans, typically '1.2+git' or '1.3.2'
    summary: Program autoskola-free8 for the schools of drive # 79 char long summary
    description: |
        Simply study your school of drive questions.

    grade: stable # must be 'stable' to release into candidate/stable channels
    confinement: strict # use 'strict' once you have the right plugs and slots

    apps: 
      autoskola-free8:
        command: python autoskola-free8.py
        plugs:
          - network

    parts:
      autoskola-free8.py:
        plugin: python
        source: ""
        source-tag: v8
        stage-packages: 
          - tk
          - tk-inter

The app tkinter code is similar to this, which needs to read /data folder in snap and write to sqlite db in snap folder. How to do that snap? I can’t create snap in linux getting errors. THANKS FOR HELP!

# !/usr/bin/python3
#License: MIT, free software
#author: lesna.vevericka@gmail.com
from tkinter import *
from tkinter import filedialog as fd
from tkinter import ttk
from tkinter.messagebox import showinfo
import datetime
import sqlite3
from sqlite3 import Error


# Some variables defined to see if db file is selected
filename1 = None
filename2=None
db_create_dir = None

# Generate new database file based on current date and time
def generate_new_database_file_name():
    now = datetime.datetime.now()
    # Generating random database name based on date and time
    rnd_db_name="db_"+str(now.day)+"_"+str(now.month)+"_"+str(now.year)+"_"+str(now.hour)+"_"+str(now.minute)+"_"+str(now.second)+".sqlite"
    # Returning random database name:
    return str(rnd_db_name)

#const: no file name selected
def no_file_name_selected():
    return "No file selected..."

# Select file dialog to load database *.sqlite
def select_file():
    filetypes = (
        ('Databases sqlite3', '*.sqlite'),
    )

    global filename1
    filename1 = fd.askopenfilename(
        title='Open a database file:',
        initialdir='./',
        filetypes=filetypes)

    if str(filename1).strip()=="":
        filename1=str(no_file_name_selected())
    showinfo(
        title='Selected File',
        message=filename1
    )

# Procedure for menu item to load database file
def load_store():
    select_file()
    global filename2
    if str(filename1).strip()!=str(no_file_name_selected()):
        filename2=filename1 # due to function save_edited_items() filename2 is not None
        msg_to_load_or_create.after(1000, msg_to_load_or_create.destroy())
        print("Loading store from database file: "+str(filename1))
        try:
            conn = None
            conn = sqlite3.connect(filename1) # It's dir with generated filename path
            sql1="SELECT * FROM items"
            c = conn.cursor()
            c.execute(sql1)
            items=c.fetchall()
            current_items.delete(1,END)
            for rec in items:
                current_items.insert(str(rec[0]),str(rec[0])+", "+str(rec[1])+", "+str(rec[2])+", "+str(rec[3])+", "+str(rec[4]))
            
        except Error as e:
            print("Error occured reading database file: "+str(e))
            showinfo(
                title='Database operation error:',
                message=str(e)
            )
        finally:
            if conn:
                conn.close()
        
        




# Ask for directory to create new empty database file layout with 1 example item
def create_empty_db():
    global db_create_dir
    db_create_dir = fd.askdirectory(
        title="Select directory for new empty database:",
        initialdir="./"
        )
    print("Creating empty database for Stores program: " + str(db_create_dir))
    if str(db_create_dir).strip()!="":
        msg_to_load_or_create.after(1000, msg_to_load_or_create.destroy())
        db_create_dir=str(db_create_dir)
        db_create_dir+="/"+generate_new_database_file_name() #Now it is directory with filename path
        global filename2 #this is intersection between filename1 and db_create_dir, always set one of them
        filename2=db_create_dir # due to function save_edited_items() filename2 is not None
        print("New database: "+db_create_dir)
        showinfo(
                title='Database will be saved here:',
                message=str(db_create_dir)
            )
        try:
            conn = None
            conn = sqlite3.connect(db_create_dir) # It's dir with generated filename path
            print("Using sqlite version: "+sqlite3.version)
            sql_create_items_table = """ CREATE TABLE IF NOT EXISTS items (
                                        id integer PRIMARY KEY,
                                        item text NOT NULL,
                                        remark1 text NOT NULL,
                                        remark2 text NOT NULL,
                                        remark3 text NOT NULL
                                    ); """
            
            c = conn.cursor()
            c.execute(sql_create_items_table)
            conn.commit()
            qry="insert into items (id, item, remark1, remark2, remark3) values(null, 'Example item JH4285', 'Rem1', 'Rem2', 'Rem3');"
            c.execute(qry)
            conn.commit()
            sql1="SELECT * FROM items"
            c.execute(sql1)
            items=c.fetchall()
            current_items.delete(1,END)
            for rec in items:
                current_items.insert(str(rec[0]),str(rec[0])+", "+str(rec[1])+", "+str(rec[2])+", "+str(rec[3])+", "+str(rec[4]))
        except Error as e:
            print("Error occured creating database file: "+str(e))
            showinfo(
                title='Database operation error:',
                message=str(e)
            )
        finally:
            if conn:
                conn.close()

#Searches in databse for mentioned item, this is executable function for db and listbox
def search_in_database():
    if search_text_box.get().strip()=="":
        showinfo(
                title='Database query operation:',
                message='Please add at least 1 character into the search box.'
        )
        return
    else:
        print("In search box: "+search_text_box.get()+" | selected db column: "+str(value_in_search_radio.get()))
        if str(value_in_search_radio.get())=='1':
            try:
                conn = None
                conn = sqlite3.connect(filename2) # It's dir with generated filename path
                c = conn.cursor()
                sql1="SELECT * FROM items WHERE item LIKE '%"+search_text_box.get()+"%';"
                c.execute(sql1)
                items=c.fetchall()
                current_items.delete(1,END)
                for rec in items:
                    current_items.insert(str(rec[0]),str(rec[0])+", "+str(rec[1])+", "+str(rec[2])+", "+str(rec[3])+", "+str(rec[4]))
            except Error as e:
                print("Error occured searching database file: "+str(e))
                showinfo(
                    title='Database operation error:',
                    message=str(e)
                )
            finally:
                if conn:
                    conn.close()
        if str(value_in_search_radio.get())=='2':
            try:
                conn = None
                conn = sqlite3.connect(filename2) # It's dir with generated filename path
                c = conn.cursor()
                sql1="SELECT * FROM items WHERE remark1 LIKE '%"+search_text_box.get()+"%';"
                c.execute(sql1)
                items=c.fetchall()
                current_items.delete(1,END)
                for rec in items:
                    current_items.insert(str(rec[0]),str(rec[0])+", "+str(rec[1])+", "+str(rec[2])+", "+str(rec[3])+", "+str(rec[4]))
            except Error as e:
                print("Error occured searching database file: "+str(e))
                showinfo(
                    title='Database operation error:',
                    message=str(e)
                )
            finally:
                if conn:
                    conn.close()
        if str(value_in_search_radio.get())=='3':
            try:
                conn = None
                conn = sqlite3.connect(filename2) # It's dir with generated filename path
                c = conn.cursor()
                sql1="SELECT * FROM items WHERE remark2 LIKE '%"+search_text_box.get()+"%';"
                c.execute(sql1)
                items=c.fetchall()
                current_items.delete(1,END)
                for rec in items:
                    current_items.insert(str(rec[0]),str(rec[0])+", "+str(rec[1])+", "+str(rec[2])+", "+str(rec[3])+", "+str(rec[4]))
            except Error as e:
                print("Error occured searching database file: "+str(e))
                showinfo(
                    title='Database operation error:',
                    message=str(e)
                )
            finally:
                if conn:
                    conn.close()
        if str(value_in_search_radio.get())=='4':
            try:
                conn = None
                conn = sqlite3.connect(filename2) # It's dir with generated filename path
                c = conn.cursor()
                sql1="SELECT * FROM items WHERE remark3 LIKE '%"+search_text_box.get()+"%';"
                c.execute(sql1)
                items=c.fetchall()
                current_items.delete(1,END)
                for rec in items:
                    current_items.insert(str(rec[0]),str(rec[0])+", "+str(rec[1])+", "+str(rec[2])+", "+str(rec[3])+", "+str(rec[4]))
            except Error as e:
                print("Error occured searching database file: "+str(e))
                showinfo(
                    title='Database operation error:',
                    message=str(e)
                )
            finally:
                if conn:
                    conn.close()


# Searches the store for mentioned item search_query1, this is the form of search
def search_this_store():
    if filename2 is None:
        showinfo(
                title='Database query operation:',
                message='Please load or create database in the menu first.'
        )
        return
    global root4
    root4 = Toplevel()
    root4.grab_set()
    root4.title('Searching in database')
    root4.geometry('400x300')
    root4.minsize(400, 300)
    root4.maxsize(400, 300)
    entry_width=45       
    search_label=Label(root4,text='Select search query:')
    search_label.pack()
    global search_text_box
    search_text_box = ttk.Entry(root4, width=entry_width)
    search_text_box.delete(0,END)
    search_text_box.pack()
    global value_in_search_radio
    value_in_search_radio=StringVar()
    chart_type_1 = ttk.Radiobutton(root4, text="search item column in database",variable=value_in_search_radio,value='1')#
    chart_type_1.pack()
    chart_type_2 = ttk.Radiobutton(root4, text="search remark1 column in database",variable=value_in_search_radio,value='2')#
    chart_type_2.pack()
    chart_type_3 = ttk.Radiobutton(root4, text="search remark2 column in database", variable=value_in_search_radio, value='3')  #
    chart_type_3.pack()
    chart_type_4=ttk.Radiobutton(root4,text="search remark3 column in database",variable=value_in_search_radio,value='4')
    chart_type_4.pack()
    value_in_search_radio.set('1')  # intended to be set as default
    search_btn = Button(root4, text = "Search in database", command= search_in_database)
    search_btn.pack()

# Insert items from form to the database
def insert_items():
    inserts2=[]
    inserts2.append('null')
    inserts2.append(item_text_box2.get())
    inserts2.append(rem1_text_box2.get())
    inserts2.append(rem2_text_box2.get())
    inserts2.append(rem3_text_box2.get())
    print(str(inserts2))
    try:
        conn = None
        conn = sqlite3.connect(filename2) # It's dir with generated filename path
        sql_insert = """ INSERT INTO items
                            (id, item, remark1, remark2, remark3) 
                            VALUES( """+inserts2[0]+""",
                                '"""+inserts2[1]+"""',
                                '"""+inserts2[2]+"""',
                                '"""+inserts2[3]+"""',
                                '"""+inserts2[4]+"""'
                                ); """
            
        c = conn.cursor()
        c.execute(sql_insert)
        conn.commit()
        showinfo(
                title='Database insert operation:',
                message='Database inserted with added inserts.'
        )
        root3.destroy()
        sql1="SELECT * FROM items"
        c.execute(sql1)
        items=c.fetchall()
        current_items.delete(1,END)
        for rec in items:
            current_items.insert(str(rec[0]),str(rec[0])+", "+str(rec[1])+", "+str(rec[2])+", "+str(rec[3])+", "+str(rec[4]))
    except Error as e:
        print("Error occured inserting values into database file: "+str(e))
        showinfo(
            title='Database operation error:',
            message=str(e)
        )
    finally:
        if conn:
            conn.close()

# Add new item to the store via given form, id is autoincrement
def add_item_to_this_store():
    if filename2 is None:
        showinfo(
                title='Database operation error:',
                message='Please create or load database to use.'
            )
        return
    global inserts2
    inserts2=[]
    global root3
    root3 = Toplevel()
    # Grab Set makes initial window root blank, so you can have open only 1 toplevel
    root3.grab_set()
    root3.title('Adding item to database')
    root3.geometry('400x300')
    root3.minsize(400, 300)
    root3.maxsize(400, 300)
    entry_width=45       
    ID_label2=Label(root3,text='ID (stays as autoincrement key):')
    ID_label2.pack()
    item_label2=Label(root3,text='Item:')
    item_label2.pack()
    global item_text_box2
    item_text_box2 = ttk.Entry(root3, width=entry_width)
    item_text_box2.delete(0,END)
    item_text_box2.pack()
    rem1_label2=Label(root3,text='Remark 1:')
    rem1_label2.pack()
    global rem1_text_box2
    rem1_text_box2 = ttk.Entry(root3, width=entry_width)
    rem1_text_box2.delete(0,END)
    rem1_text_box2.pack()
    rem2_label2=Label(root3,text='Remark 2:')
    rem2_label2.pack()
    global rem2_text_box2
    rem2_text_box2 = ttk.Entry(root3, width=entry_width)
    rem2_text_box2.delete(0,END)
    rem2_text_box2.pack()
    rem3_label2=Label(root3,text='Remark 3:')
    rem3_label2.pack()
    global rem3_text_box2
    rem3_text_box2 = ttk.Entry(root3, width=entry_width)
    rem3_text_box2.delete(0,END)
    rem3_text_box2.pack()
    save_edited_item2 = Button(root3, text = "Insert these values", command= insert_items)
    save_edited_item2.pack()

def edit_item_in_this_store():
    showinfo(
                title='Edit item in this store:',
                message="Please, double click selected item in the listbox."
            )

# Sql commands for database to update current selection of edited item cs in entries=what_to_update, filename1 or db_create_dir=what_filename
def update_edited_items_in_db(what_to_update, what_filename):
    try:
        conn = None
        conn = sqlite3.connect(what_filename) # It's dir with generated filename path
        sql_insert = """ UPDATE items
                            SET id = '"""+what_to_update[0]+"""',
                                item = '"""+what_to_update[1]+"""',
                                remark1 = '"""+what_to_update[2]+"""',
                                remark2 = '"""+what_to_update[3]+"""',
                                remark3 = '"""+what_to_update[4]+"""'
                            WHERE
                                id = """+what_to_update[0]+"""; """
            
        c = conn.cursor()
        c.execute(sql_insert)
        conn.commit()
        showinfo(
                title='Database update operation:',
                message='Database updated with current selection entries.'
        )
        root2.destroy()
        sql1="SELECT * FROM items"
        c.execute(sql1)
        items=c.fetchall()
        current_items.delete(1,END)
        for rec in items:
            current_items.insert(str(rec[0]),str(rec[0])+", "+str(rec[1])+", "+str(rec[2])+", "+str(rec[3])+", "+str(rec[4]))
    except Error as e:
        print("Error occured updating database file: "+str(e))
        showinfo(
            title='Database operation error:',
            message=str(e)
        )
    finally:
        if conn:
            conn.close()    

# Saves entries from editing the item values form called root2
def save_edited_items():
    entries=[]
    entries.append(ID_text_box.get())
    entries.append(item_text_box.get())
    entries.append(rem1_text_box.get())
    entries.append(rem2_text_box.get())
    entries.append(rem3_text_box.get())
    # Save entries[0] which is ID for update statement in db, can't change/load from form entry
    entries[0]=init_entries.split(",")[0].strip()
    print(str(entries))
    if filename2 is not None:
        # If you loaded/created store db, use this name path
        update_edited_items_in_db(entries, filename2)

# Deletes item from editing form based on the id key which is not being edited but constant id for manipulation
def delete_edited_items():
    try:
        # init_entries contains comma separated values from double click on the list box, so one row
        # we can split init_entries string by comma and get 0 value which is ID
        print("Deleting ID from database: "+str(init_entries.split(",")[0].strip()))
        conn = None
        conn = sqlite3.connect(filename2) # It's dir with generated filename path
        sql_insert = """ DELETE FROM items
                            WHERE id = """+init_entries.split(",")[0].strip()+""";"""
            
        c = conn.cursor()
        c.execute(sql_insert)
        conn.commit()
        showinfo(
                title='Database delete operation:',
                message='Database deleted for ID='+str(init_entries.split(",")[0].strip())
        )
        root2.destroy()
        sql1="SELECT * FROM items"
        c.execute(sql1)
        items=c.fetchall()
        current_items.delete(1,END)
        for rec in items:
            current_items.insert(str(rec[0]),str(rec[0])+", "+str(rec[1])+", "+str(rec[2])+", "+str(rec[3])+", "+str(rec[4]))
    except Error as e:
        print("Error occured deleting from database file: "+str(e))
        showinfo(
            title='Database operation error:',
            message=str(e)
        )
    finally:
        if conn:
            conn.close()


# Will edit selected item in the listbox after double click in edit window
# cs is current selection containing one selected row from listbox with item
def edit_selected_item_in_the_listbox(cs):
    global init_entries
    init_entries = cs # Saving state of ID, ID can not be changed, we are editing item
    if (cs.split(",")[0]) == "ID":
        showinfo(
                title='Double clicked description item:',
                message="Please, select some REAL item. Not the legend."
            )
    else:
        global root2
        root2 = Toplevel()
        root2.grab_set()
        root2.title('Editing item')
        root2.geometry('400x300')
        root2.minsize(400, 300)
        root2.maxsize(400, 300)
        entry_width=45       
        ID_label=Label(root2,text='ID (stays unedited as key):')
        ID_label.pack()
        global ID_text_box
        ID_text_box = ttk.Entry(root2, width=entry_width)
        ID_text_box.delete(0,END)
        ID_text_box.insert(0,cs.split(",")[0].strip())
        ID_text_box.pack()
        item_label=Label(root2,text='Item:')
        item_label.pack()
        global item_text_box
        item_text_box = ttk.Entry(root2, width=entry_width)
        item_text_box.delete(0,END)
        item_text_box.insert(0,cs.split(",")[1].strip())
        item_text_box.pack()
        rem1_label=Label(root2,text='Remark 1:')
        rem1_label.pack()
        global rem1_text_box
        rem1_text_box = ttk.Entry(root2, width=entry_width)
        rem1_text_box.delete(0,END)
        rem1_text_box.insert(0,cs.split(",")[2].strip())
        rem1_text_box.pack()
        rem2_label=Label(root2,text='Remark 2:')
        rem2_label.pack()
        global rem2_text_box
        rem2_text_box = ttk.Entry(root2, width=entry_width)
        rem2_text_box.delete(0,END)
        rem2_text_box.insert(0,cs.split(",")[3].strip())
        rem2_text_box.pack()
        rem3_label=Label(root2,text='Remark 3:')
        rem3_label.pack()
        global rem3_text_box
        rem3_text_box = ttk.Entry(root2, width=entry_width)
        rem3_text_box.delete(0,END)
        rem3_text_box.insert(0,cs.split(",")[4].strip())
        rem3_text_box.pack()
        save_edited_item = Button(root2, text = "Save these values", command= save_edited_items)
        save_edited_item.pack()
        delete_edited_item = Button(root2, text = "Delete these values", command= delete_edited_items)
        delete_edited_item.pack()

# Function called after double click on the item in the listbox
def dbl_clicked_item_in_listbox(event):
    try:
        # cs is current selection in the list box to work with after double click
        cs=current_items.selection_get()
        print("Selected to edit: "+str(cs))
        if filename1 is None and db_create_dir is None:
            print("No database file created or selected. Please click menu for this.")
            showinfo(
                title='Double clicked item:',
                message="No database file created or selected. Please click menu for this."
            )
        else:
             edit_selected_item_in_the_listbox(cs)       
    except Error as e:
        print(str(e))

root = Tk()
root.title('Stores v22.3-codename: Jirmejahu')
root.geometry('400x300')
# set minimum window size value
root.minsize(400, 300)
# set maximum window size value
root.maxsize(400, 300)
# Creating Menubar 
menubar = Menu(root) 
# Adding Home Menu
home = Menu(menubar, tearoff = 0) 
menubar.add_cascade(label ='Load store', menu = home)
home.add_command(label="Load store from file", command=load_store)
home.add_command(label="Create empty database file", command=create_empty_db)
searchit = Menu(menubar, tearoff = 0) 
menubar.add_cascade(label ='Search store', menu = searchit)
global search_query1
search_query1=""
searchit.add_command(label="Search items in this store", command=search_this_store)
searchit.add_command(label="Add new item to this store", command=add_item_to_this_store)
searchit.add_command(label="Edit item in this store=double click", command=edit_item_in_this_store)
# display Menu 
root.config(menu = menubar)
#Display message to load or create database first
global msg_to_load_or_create
msg_to_load_or_create=Label(
    root,
    text='Load or create database file, please.',
)
msg_to_load_or_create.pack(side="top")
# Setting scrollbars and Listbox
scrollbar1 = Scrollbar(root, orient=VERTICAL)
scrollbar2 = Scrollbar(root, orient=HORIZONTAL)
current_items = Listbox(root, height=15, width=60, yscrollcommand=scrollbar1.set)
current_items.insert(0, 'ID, Item Name, Remark1, Remark2, Remark3')
current_items.bind('<Double-1>', dbl_clicked_item_in_listbox)
scrollbar1.config(command=current_items.yview)
scrollbar1.pack(side=RIGHT, fill=Y)
scrollbar2.config(command=current_items.xview)
scrollbar2.pack(side=BOTTOM, fill=X)
current_items.pack()
root.mainloop()

I see, they do not have the solution to tkinter in python even here: ModuleNotFoundError: No module named ‘tkinter’ - snapcraft - snapcraft.io

Hey there, I found some answers on python snaps here: https://www.youtube.com/watch?v=jG7FN1sbdD4