Python Forum
How do I run background functions constantly
Thread Rating:
  • 2 Vote(s) - 3.5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How do I run background functions constantly
#1
I'm brand new to Python, but I have experience with creating all types of all types of code. Because of this, I just find indexes or the small bits of info I need to get what I want done.

My main problem seems to be my overall idea of how python works. Or I'm just not sure how to get it to work how I'm used to.

My goal is to have very simplistic menus, all of which have the same background. the background will be dynamic relating to the current menu, and it'll move a number of ways. As the user transitions between menus the background continues to operate independently and is constantly updated and moving.

Because I have say, 11 menus, I'm not sure how I keep a background "process" going.
I thought I could create a global menu, then call up individual menus. But the global menu seems to stop.

On top of this, I've created a Def for clicking the mouse button up or down. Because it'll be used in every menu. When I try to use it in any menu, the only thing that becomes active is the mouse function.


How can I have a containing menu, that can switch between menus, that can call a function any time without interrupting anything?
I know I'm probably not asking the right way for the answer I need.

I'm pretty sure it goes to how the actual Def is written for my mouse click(s), but how do I get the mouse to work everywhere without writing the code everywhere?

Not sure if this helps any way, but, this is what I have for my imports right now
import locale
import sys, os
import winsound
import json
import pygame
import random
from tkinter import *
from tkinter import messagebox
from datetime import datetime
from PIL import Image, ImageFilter
Reply
#2
I cant tell from your post what youre trying to do, but maybe suggest you write some more python code to make it more clear, or perhaps draw a screenshot of what you what the project to look like when finished.

In your list of imports you have:

from tkinter import *
from tkinter import messagebox
You dont need the second line as you are importing all of the functions in the tkinter module in the previous line.

To call a function without interrupting, is called non-blocking, concurrency or multitprocessing.
What you may need is the python threading or multiprocessing module:

Here are a couple of links:
https://pymotw.com/3/threading/

https://pymotw.com/3/multiprocessing/basics.html

You may not even need these but what purpose or function does pressing abutton on your menu do?
Reply
#3
Thanks for the tip about not needing the second line. Knowing that, is there any benifit of using
from datetime import datetime
and NOT
from datetime import *
As in, would it take a ton of resources to load everything, not just datetime? Would other imports be better being restricted to only what I use?

The way I imagine the game to work, is you get a loading screen that checks for a user name, if none, you get pop ups to fill in.
Once you have the username/attributes you get 4 options,
the game,
random level,
statistics,
settings.
So the background loads in the loading screen and continues to move. Once in the game the images switch. As the timer nears 0 the images change to red and speed up.
Basically the game is going to watch for a correct/incorrect/out of time answer. all types of variables will be watched depending on the questions and answers.

Imagine just an A or B button on screen. Once one's selected, an animation plays, and the next question/level is reached or you're sent to a retry/game over screen.
I do want a "home" button and possibly two other "always active" buttons that would pop up submenus. The home button would launch a sub menu with 3 to 4 options. 1 is obviously to return you to the main menu, another would continue with the game.


The way I'm "reading" examples with their while loop and their "Def GameLoop()" makes me think each time I want the home menu to be active, I have to copy and paste the code into that menu's def/while loop. But I'm pretty sure that's what Defs are usually used for. So I can just tack 1 line in, and get all the goodness of the Home button in one easy click.
Like I'd hope that I could code the home button def, then code the "if the mouse presses in the top left corner activate the home button" and just copy paste 1 or 2 lines into each area/def/while, I need.

Thanks for the links. I'm going to look them over now.
Reply
#4
Methods to call functions without waiting for them
  • With threading. Avoid CPU bound calculations with threading. Otherwise you run into problems (GIL). When waiting for IO, they are fine. Often you have to pass an argument as callback to a function, which does something when the task has its result.
    thread = threading.Thread(target=function, args=[arg1, arg2, arg3])
    thread.start()
  • With multiprocessing, which starts a new instance of a Python interpreter. All data passed in as arguments, are serialized. It costs performance. Do only complex calculation in a process.
    process = multiprocessing.Process(target=function, args=[arg1, arg2, arg3])
    process.start()
  • Asyncio. Watch this video: https://www.youtube.com/watch?v=oJQdX_w1vXY
  • with generators, running them iterative. Here an example of a round robin scheduling. I think you do not want to use this now. But it's good to know the benefits of the powerful generators.
    from collections import deque
    # deque is a optimized list for append and pop on both sides.
    
    
    def generator_function(text):
        for i in range(10):
            yield i, text
    
    gen1 = generator_function('Hello')
    gen2 = generator_function('World')
    gen3 = generator_function('!')
    tasks = deque([gen1, gen2, gen3])
    
    while tasks:
        # something like an event loop
        # in this case the loop runs until the queue is empty
        task = tasks.popleft()
        try:
            print(next(task))
        except StopIteration:
            # throw a task away, when it's iteration is done
            pass
        else:
            # append the task to the end, if the iteration is still not complete
            # else is called when no exception was raised
            tasks.append(task)
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#5
I've been looking into this, and I think I see a way to work how I want; With threading.

My idea was to have the background always updating, to have an active menu, and a sort of pop-up menu.
So I can make
thread1
thread2
thread3
be those "menus" or tasks. Then I just set up my if/elif/else questions to see which menu to activate.
and I guess thread4 would be input? or should I rely on the active menu to look for that?

Are there any drawbacks from working in this "style"?
Reply
#6
Here an example with a simple updating listbox:
import threading
import time
from tkinter import Tk
from tkinter import Listbox
from tkinter import Variable


def update_func(list_variable):
    while True:
        # just for demonstration
        time.sleep(2)
        entries = list(list_variable.get())
        entries = entries[1:] + entries[0:1]
        list_variable.set(entries)   


def main(root):
    list_variable = Variable(root)
    list_variable.set(['foo', 'bar', 'baz'])
    thread1 = threading.Thread(target=update_func, args=[list_variable])
    # you will pass more arguments to the function, for example to check
    # conditions inside the thread
    thread1.setDaemon(True)
    # sets a Daemon-Thread. After the main thread of the python interpreter
    # has been finished/interrupted the interpreter still waits
    # for finishing non-daemon-threads
    thread1.start()
    # start the thread.
    lb = Listbox(root, listvariable=list_variable)
    lb.pack()

if __name__ == '__main__':
    root = Tk()
    main(root)
    root.mainloop()
I think it's much better to do whole GUI in a object oriented style.
It's only a demonstration with one thread which is just updating
the entries of the tuple in list_variable.

If you've just an event, which should update an entry or disable an entry, this can be done with callbacks. There you don't need a thread for it.
A thread is used for io or repeating things which just should happen in the background.
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Python Constantly Crashing mat189 0 212 Jan-22-2024, 07:18 AM
Last Post: mat189
  logging values from constantly updating CLI app imvirgo 1 504 Sep-27-2023, 05:01 PM
Last Post: deanhystad

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020