Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BUG-Variable not available in either the 'gui_instance' or '__main__' module when they are in fact in __main__ #1249

Closed
2 tasks
gbritoda opened this issue May 1, 2024 · 13 comments
Assignees
Labels
🖰 GUI Related to GUI 💥Malfunction Addresses an identified problem. 🟨 Priority: Medium Not blocking but should be addressed 🔒 Staff only Can only be assigned to the Taipy R&D team
Milestone

Comments

@gbritoda
Copy link

gbritoda commented May 1, 2024

Description and How to reproduce

My understanding is that you need to have your callbacks and variables in the same scope as where you instantiate the Gui object, OR at __main__ (the file which was called)

But I don't think that's happening. I am trying to instantiate the Gui in a separate file and have the callbacks and variables. imported to another main.py file, alongside the instantiated Gui object (the reason I need to do this is part of a bigger issue which I wont touch now).

Here's a mockup of the code in 3 different files:

callbacks_and_vars.py

from taipy.gui import notify

def test_callback(state):
    notify(state, "I", "Button was pressed")

TEST_VAR = "This is a test text"

gui_instance.py

from taipy.gui import Gui

GUI_OBJ = Gui()

main.py

from gui_instance import GUI_OBJ
from callbacks_and_vars import test_callback, TEST_VAR

GUI_OBJ.add_pages(
    {
        "/":"<|button|label={TEST_VAR}|on_action=test_callback|>"
    }
)
print(__name__)
GUI_OBJ.run()

I get the following output:

__main__
[2024-04-30 11:10:54][Taipy][INFO]  * Server starting on http://127.0.0.1:5000
WARNING:root:
--- 3 warning(s) were found for page '/'  ---
 - Warning 1: Variable 'TEST_VAR' is not available in either the 'gui_instance' or '__main__' modules.
 - Warning 2: Variable 'TEST_VAR' is not defined (in expression '{TEST_VAR}'):
'types.SimpleNamespace' object has no attribute 'TEST_VAR'
 - Warning 3: button.on_action: test_callback is not a function.
----------------------------------------------

I am particularly suspicious of the warning that says - Warning 1: Variable 'TEST_VAR' is not available in either the 'gui_instance' or '__main__' modules., because that's not the case, everything is in the __main__ module.

Expected behavior
The GUI file should have the variables in its cope as they are present in __main__

Screenshots
image

Runtime environment
Please specify relevant indications.

  • Taipy version: 3.1.0
  • OS: Windows 11 but running on WSL

Acceptance Criteria

  • Ensure new code is unit tested, and check code coverage is at least 90%
  • Create related issue in taipy-doc for documentation and Release Notes if relevant
@gbritoda gbritoda added the 💥Malfunction Addresses an identified problem. label May 1, 2024
@jrobinAV jrobinAV added 🖰 GUI Related to GUI 🟨 Priority: Medium Not blocking but should be addressed 🔒 Staff only Can only be assigned to the Taipy R&D team labels May 2, 2024
@FabienLelaquais
Copy link
Member

One way of dealing with that would be to add a setting for the variable scope in the Gui constructor.

@dinhlongviolin1
Copy link
Member

dinhlongviolin1 commented May 14, 2024

Hi, for this use case of yours it is important to place everything next to each other so Taipy GUI can handle things properly. If you want to do multi pages, you can visit this section on the doc. Let me know if you have any further question

@gbritoda
Copy link
Author

gbritoda commented May 14, 2024

Hi @dinhlongviolin1 , this unfortunately doesn't apply for my use case. The code here is a simplification.

The reason I am structuring it like this is because I need to declare the Gui instance before some callbacks due to me running a bunch of different callbacks in different threads that need the state variable, thus needing the Gui instance as their parameter.

I needed that back in Taipy 2.4.0, dont know if there's a better way to do this, I based that from https://docs.taipy.io/en/release-2.1/manuals/gui/callbacks/#long-running-callbacks-in-a-thread

In short, it's something like this:

gui_instance.py

from taipy.gui import Gui

GUI_OBJ = Gui()

callbacks_and_vars.py

from gui_instance import GUI_OBJ
from taipy.gui import notify, get_state_id, invoke_callback

def _test_loop(state):
     # (...) do stuff with state like state.refresh in a loop for a while
    notify(state, "I", "Button was pressed")

def start_test_loop(state_id:str):
    invoke_callback(GUI_OBJ, state_id, _test_loop, args=[])

def test_callback(state):
     loop_thread = threading.Thread(target=start_test_loop, args=[get_state_id(state), daemon=True)
     loop_thread.start()
     # (...) do other things in parallel

TEST_VAR = "This is a test text"

main.py

from gui_instance import GUI_OBJ
from callbacks_and_vars import test_callback, TEST_VAR

GUI_OBJ.add_pages(
    {
        "/":"<|button|label={TEST_VAR}|on_action=test_callback|>"
    }
)
print(__name__)
GUI_OBJ.run()

This is the only way of structuring the files that I can see that avoids a circular import of GUI_OBJ

@gbritoda
Copy link
Author

But I am importing everything into main.py, so that should work no? Especially because the message says either at __main__ or at where the Gui was declared

@dinhlongviolin1
Copy link
Member

Thanks for getting back to me. The thing that I don't really understand is why you need the Gui instance declare before everything else. The state within the Gui won't be there until the application is up. You can declare it and it will be executed later on. If you really want this structure, what I will suggest you trying out is this structure. Let me know if it helps.

gui_instance.py

from taipy.gui import Gui

GUI_OBJ = Gui()

callbacks_and_vars.py

from gui_instance import GUI_OBJ
from taipy.gui import notify, get_state_id, invoke_callback, Markdown

def _test_loop(state):
     # (...) do stuff with state like state.refresh in a loop for a while
    notify(state, "I", "Button was pressed")

def start_test_loop(state_id:str):
    invoke_callback(GUI_OBJ, state_id, _test_loop, args=[])

def test_callback(state):
     loop_thread = threading.Thread(target=start_test_loop, args=[get_state_id(state), daemon=True)
     loop_thread.start()
     # (...) do other things in parallel

TEST_VAR = "This is a test text"

page = Markdown("<|button|label={TEST_VAR}|on_action=test_callback|>")

main.py

from gui_instance import GUI_OBJ
from callbacks_and_vars import page as page1

GUI_OBJ.add_page("page1", page1)
print(__name__)
GUI_OBJ.run()

@gbritoda
Copy link
Author

gbritoda commented May 14, 2024

Hi, I need it for the start_test_loop, it needs the GUI already instantiated.

This structure of yours is the same as the code as I just wrote in regards to variable scope isn't it? Everything is imported to __main__, but it won't work as everything needs to be in gui_instance, which is where GUI_OBJ is created.

The issue is that the error message that I get is - Warning 1: Variable 'TEST_VAR' is not available in either the 'gui_instance' or '__main__' modules., so that code should indeed work

@dinhlongviolin1
Copy link
Member

If you do it as I did and create a Markdown instance as a page, it will work since it will consider that a moudle of its own. We call that one Page Scopes. Please give it a try.

@gbritoda
Copy link
Author

will do! Thanks

@gbritoda
Copy link
Author

Wow, it worked! Thank you so much for this. Will try it on my bigger application and see how it goes but I am now much more optmist.

@gbritoda
Copy link
Author

@dinhlongviolin1 in that case, however, do all pages need to be declared in the same file? Or can they be declared in different files then imported into main.py? And what about the callbacks, they need to be where exactly? Because youre not importing them into main.py so I imagine it needs to be within the same scope as the Markdown?

@dinhlongviolin1
Copy link
Member

Yes, your assumption is correct. All the variables + functions should be included within the same file/module as the Markdown instance. You can add multiple Markdown instances in different files to create a multi page application.

@dinhlongviolin1
Copy link
Member

I will close the issue. If you have any problem, you can open a new issue or contact me directly through nguyen.dinh.long@taipy.io

@gbritoda
Copy link
Author

Hi @dinhlongviolin1, but I think the issue is still not addressed.

Sure we have made the code work for my case but this looks more of a workaround. The warning message states that the variable should be in either gui_instance or in __main__, but the warning does not go away even when the variable is explicitly imported into __main__. So I'd argue that either the message is wrong or the behaviour is not expected. Wouldn't you agree?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🖰 GUI Related to GUI 💥Malfunction Addresses an identified problem. 🟨 Priority: Medium Not blocking but should be addressed 🔒 Staff only Can only be assigned to the Taipy R&D team
Projects
None yet
Development

No branches or pull requests

5 participants