Multiple copies of function vs single copy in py file

54 views
Skip to first unread message

Dan Moormann

unread,
Jul 18, 2024, 2:31:36 PM (9 days ago) Jul 18
to Kivy users support
In trying to keep from having multiple copies of a function in 3 screens, I put a single copy of the function in a py file.

 Either approach works in windows but the single/py version fails after using buildoze to port to android.  The multiple version works on windows and android using the same buildozer spec.

I added an if test xtest= 0 or 1(line 49 and 58) to call the single or multiple version.  Both versions work on windows.  The multiple approach works on android, but the single approach fails with the app quitting without any obvious error.

Nothing useful shows up in the log file.  Perhaps I'm not getting the log from the install/open option on android.




log.txt
grid.kv
readwrite.py
linenum.py
grid.py
buildozer.spec
settings.txt
readwrite.py

ElliotG

unread,
Jul 18, 2024, 8:39:23 PM (9 days ago) Jul 18
to Kivy users support
I believe the problem is in the readwrite.py file you are importing platform.  You need to change:
import platform
to:
from kivy.utils import platform

Some other suggestions:
1) You may also want to use try/except to see if you can catch an OSError.  
2) I'd be concerned with the absolute addressing you are using under Windows.  I would recommend creating the path using __file__ or just use relative addressing. The way you are creating the path for android should also work on windows.
3) I'd recommend using pathlib vs os.path.  I find it much nicer to work with.
4) use a context manager to open and close the file.  It handles the close automatically and does an better job of handling exceptions.
you could use this instead of the way you are doing this now.
6) The way you are creating the path for android should also work on windows.

I would also recommend creating two functions read_grid_settings(), write_grid_settings().  These two functions will be simpler and it will also be clearer what they are doing.

As always happy to answer any questions on these recommendations... or anything else :)



ElliotG

unread,
Jul 18, 2024, 8:42:22 PM (9 days ago) Jul 18
to Kivy users support
Another option to consider is making these methods of app.  That will also make it easy to access these from anywhere in the app. 

Dan Moormann

unread,
Jul 19, 2024, 12:34:56 AM (8 days ago) Jul 19
to Kivy users support
Your suggestion for from kivy.utils import platform worked for windows and android.  I've deleted the multiple copies.  Don't understand why kivy.utils made the difference as the code was identical.

If I use try/except, where would the error show up?  I'm not getting errors in windows version, only android (before the fix).

Since I only intend to use the windows version on my own computer, I don't see the need to deviate from absolute addressing.  But I will keep that in mind if I change my mind later.

I wanted to split the read and write funtions into two but didn't see the point of duplicating the file open step.  

I looked at the pathlib, user_data_dir and context manager - a bit over my head.

ELLIOT GARBUS

unread,
Jul 19, 2024, 11:10:04 AM (8 days ago) Jul 19
to kivy-...@googlegroups.com
"Don't understand why kivy.utils made the difference as the code was identical."

When you import platform you are bringing in the standard library module named platform.  Run this experiment:

import platform
print(platform)

The output will be something like: 
<module 'platform' from 'C:\\Users\\ellio\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\platform.py'>

This will never be "android"

You could use try/except to log an error.  You could then see a clear error in the log.

Somthing like:
try:
    with open(filename) as f:
        data = f.read()
        ...
except OSError as e:
   Logger.exception(f'file read error in setting_read() {filename} {e}')
   
This would leave a useful message in the log.

"Since I only intend to use the windows version on my own computer, I don't see the need to deviate from absolute addressing. " 
If you change directories, or move to a new computer you could have a set or errors to fix.

A context manager in python handles enter and exit conditions automatically.  Specifically for a file it automatically closes the file and cleanly handles closing the file if an exception occurs.
Read the first few paragraphs here, the describe how to use a context manager and what it is doing.   Don't worry about how to implement them: https://book.pythontips.com/en/latest/context_managers.html#context-managers 

Splitting the read and write make the code more readable and maintainable.  It makes it very easy to understand what is happening where the function is called.

The user_data_dir is a directory string that is created by kivy that puts user data in (generally) the right place for user data for each platform.   Run this experiment on Windows and Android:

from kivy.app import App
from kivy.lang import Builder

kv = """
Label:
    text: app.user_data_dir
"""


class MyUserDatDirApp(App):
    def build(self):
        return Builder.load_string(kv)

    def on_start(self):
        print(f'{self.user_data_dir=}')


MyUserDatDirApp().run()

On my Windows machine I see:  self.user_data_dir='C:\\Users\\ellio\\AppData\\Roaming\\myuserdatdir'

Here is a small pathlib example, relevant to your code:

from pathlib import Path

path = Path().cwd() / 'settings.txt'
print(path)

base_path = Path(__file__).parent
settings_path = base_path / 'settings.text'
print(base_path)
print(settings_path)


From: kivy-...@googlegroups.com <kivy-...@googlegroups.com> on behalf of Dan Moormann <dan...@gmail.com>
Sent: Thursday, July 18, 2024 9:34 PM
To: Kivy users support <kivy-...@googlegroups.com>
Subject: [kivy-users] Re: Multiple copies of function vs single copy in py file
 
--
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/143382e2-adce-42b1-a240-0aed756fe619n%40googlegroups.com.

Dan Moormann

unread,
Jul 21, 2024, 12:23:51 AM (6 days ago) Jul 21
to Kivy users support
I'm having some success implementing separate functions in readwrite for read, write, print, setup, etc.  
I'm getting unusual behavior (at least for me) for importing.  
It seems I have to import linenum.println for kv, and import from readwrite linenum for py.  Any other combination causes errors. The linenum code is identical/duplicated.

Any idea why this is the case?

Is from readwrite import * valid?  When I tried it, I got an error.
readwrite.py
grid.kv
linenum.py
settings.txt
grid.py

ElliotG

unread,
Jul 21, 2024, 10:18:27 AM (6 days ago) Jul 21
to Kivy users support
In kv you can import println as:
#:import println readwrite.println
works fine for me.

I can also do "from readwrite import *" with no issue.
It is not advised to use import *, this will bring in all of the symbols and will "pollute" the namespace.  Better to explicitly bring in the names you want.  This can avoid namespace conflicts where you have variables with the same name in different modules.  read: https://www.geeksforgeeks.org/why-import-star-in-python-is-a-bad-idea/

Dan Moormann

unread,
Jul 22, 2024, 11:29:03 PM (4 days ago) Jul 22
to Kivy users support
Progress is slow.  Re-writing for the 5th or 6th time.  Trying to do a single read operation so I put it in on_kv_post.  Since I need the settings in crawl and setting I try to grab the needed settings with grab_settings.  It grabs setting_text but dies with an attribute error for set_fontsize and/or set_velocity.
   File "C:\Users\danm9\grid\grid.kv", line 378, in <module>
     root.grab_settings()
   File "C:\Users\danm9\grid\grid.py", line 634, in grab_settings
     self.ids.set_fontsize.text=self.manager.get_screen('Main').setting_font_size
     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 AttributeError: 'str' object has no attribute 'text'

Why does it think set_fontsize is a str and not a SingleLineTextInput widget
grid.py
settings.txt
linenum.py
grid.kv
readwrite.py

ElliotG

unread,
Jul 23, 2024, 12:55:05 AM (4 days ago) Jul 23
to Kivy users support
Look at the last two lines in Main.on_kv_post... you are overwriting the ids dict...

It should be:
self.manager.get_screen('setting').ids.set_velocity.text = self.setting_velocity
self.manager.get_screen('setting').ids.set_fontsize.text = self.setting_font_size
Reply all
Reply to author
Forward
0 new messages