pythonarcade/arcade

arcade corrupts python environment

Closed this issue · 6 comments

Bug Report arcade corrupts python environment

System Info Windows 10 Home, 64-bit OS

Run this and paste the output here: python -m arcade

Arcade 2.6.17
vendor: ATI Technologies Inc.
renderer: AMD Radeon(TM) R3 Graphics
version: (4, 5)
python: 3.8.0 (tags/v3.8.0:fa919fd, Oct 14 2019, 19:37:50) [MSC v.1916 64 bit (AMD64)]
platform: win32

Actual behavior: PySimpleGUI functionality broken after simply importing arcade

Expected behavior: importing arcade should not change python environment

Steps to reproduce/example code: (Apologies, cannot get code insertion to format properly with backtick)

`
"""
On Windows 10 runs correctly under python 3.8
The FolderBrowse hangs when selected if I
unhide the "import arcade" line.
Aside: FileBrowse operation changed as well.
"""

import PySimpleGUI as sg
"""import arcade"""

""" Define the layout of the GUI"""
layout = [
[sg.Text("Select a folder:")],
[sg.Input(key="-FOLDER-"), sg.FolderBrowse()],
[sg.Button("OK"), sg.Button("Cancel")]
]

""" Create the window"""
window = sg.Window("Folder Browser", layout)

""" Event loop"""
while True:
event, values = window.read()
if event == sg.WINDOW_CLOSED or event == "Cancel":
break
elif event == "OK":
selected_folder = values["-FOLDER-"]
sg.popup(f"Folder selected: {selected_folder}")
break

""" Close the window"""
window.close()
`

Enhancement request: N/A

What should be added/changed? N/A

What would it help with?

Modularity.

Documentation request:

What documentation needs to change?

Where is it located?

What is wrong with it? How can it be improved?

Although my application is not run-of-the-mill I expect to be able to run various modules sequentially without interaction occurring. The initial implementation of my project was alternating between PySimpleGUI windows and Pygame windows. Because Pygame was exhibiting occasional erratic event handling, I reimplemented using kivy. Then I find that kivy always exhibits a default window from startup. I have a workaround for the arcade problem here which was to simply delay the arcade import until after my first PySimpleGUI configuration screen, the only one that uses FileBrowse and FolderBrowse. To be truely useful it would be nice to be able to "unhook", "rehook" the arcade software from the python environment so that it works with other python modules seamlessly.

cannot get code insertion to format properly

It requires three backticks followed by the language name, as shown here in the GitHub doc.

To be truely useful it would be nice to be able to "unhook", "rehook" the arcade software from the python environment so that it works with other python modules seamlessly.

My suspicion is this isn't something arcade-specific, but an interaction between pyglet and whichever backend you're using for PySimpleGUI. Although pyglet is used as the basis of arcade and supports multiple windows, arcade assumes the user will only have one window at a time. Kivy also seems to make an assumption like this, except it goes further and assumes that there will always be a window. These sorts of assumptions could be the roots of event handling issues and unusual interactions between modules.

The easiest fix might be to spawn separate processes for each window and use IPC if you need multiple windows, or use a library such as plyer to bind platform-native file browser functionality instead.

If you're still determined to try mixing PySimpleGUI with arcade, can you try the following?

  1. See if you can replicate these issues with pyglet and your other windows
  2. See if you can change the back-end for PySimpleGUI to use tk

There's at least one user who has used tkinter to build tool windows to use with arcade's main window as a way to circumvent the one-window limitation of arcade.

Thanks pushfoo, I was just using the <> "Add code" option on the title bar, now I know the correct syntax. I am using the tk version of PySimpleGUI.

However I don't think one can blame pyglet for the issue I am having because the following code runs correctly:

#
# On Windows 10 runs correctly under python 3.8
# The FolderBrowse hangs when selected if I
#   uncomment the "import arcade" line.
# Aside: FileBrowse operation changed as well.
#

import PySimpleGUI as sg
import pyglet

# Define the layout of the GUI
layout = [
    [sg.Text("Select a folder:")],
    [sg.Input(key="-FOLDER-"), sg.FolderBrowse()],
    [sg.Button("OK"), sg.Button("Cancel")]
]

# Create the window
window = sg.Window("Folder Browser", layout)

# Event loop
while True:
    event, values = window.read()
    if event == sg.WINDOW_CLOSED or event == "Cancel":
        break
    elif event == "OK":
        selected_folder = values["-FOLDER-"]
        sg.popup(f"Folder selected: {selected_folder}")
        break

# Close the window
window.close()

I have unfortunate news. From what I see in the well-formatted code, there is a fundamental design difference in event handling between the libraries:

  • PySimpleGUI seems to assume you'll be writing your own event loops
  • pyglet, and therefore arcade, assume you'll be using event handler functions
  • arcade assumes there will only be one window, which may cause event capture to start on import

I am not 100% sure of the last item, but it could explain the freeze. It may actually be occuring at event, values = window.read(). This seems consistent with what you said here:

have a workaround for the arcade problem here which was to simply delay the arcade import until after my first PySimpleGUI configuration screen, the only one that uses FileBrowse and FolderBrowse.

The rest of this post is uncertain guesswork. Don't trust it until you test it.

It may be possible to override the arcade / pyglet event loop with your own. However:

  1. You might run into the same kind of event handling issues you described with PyGame, which are likely due to shared / multi-window issues
  2. Any changes to this seem out of scope for arcade itself and might be better put in an add-on library

Both of these are why I suggested multiple alternatives to mixing PySimpleGUI with other libraries in the same process.

I don't think one can blame pyglet for the issue I am having

This is far more complicated than it looks. It may depend on multiple factors, including:

  • your OS
  • your pyglet version
  • your arcade version

You're also not the first to have issues with getting PySimpleGUI working with either pyglet or a library which uses it, even if those issues are different.

Since pyglet might not create any windows on import on your system, recreating the same behavior may require creating pyglet windows before the PySimpleGUI window. I'm not sure of the details of this since it's both platform specific and has had multiple bug fixes made to it over the past few years.

As to arcade, we're currently working toward 3.0.0, and there are no plans to do further work on 2.6. Since I don't have a Windows install set up at the moment, I recommend the following:

  1. If you haven't yet, make absolutely sure the freeze actually happens at the import and not event, values = window.read()
  2. Try this with arcade==3.0.0-dev26 or arcade==3.0.0dev25.The dash before dev26 matters.
  3. Try your second example with pyglet==2.0.9

If you can get plyer's file picker working and can live with its limitations, it may be the best option. It'll probably stop the game's exection while the file chooser is up, but it will probably have fewer issues than PySimpleGUI.

Good news. Although I could not pip install the dev26 version I could install the dev25 version. I then ran the original code where I imported arcade and the FileBrowse works correctly. My second version with pyglet==2.0.9 is also ok. It appears the new version has resolved my issues - I tested with the code below and the windows both work correctly.

#
# On Windows 10, python 3.8
#

import PySimpleGUI as sg
import arcade

def gui():
    # Define the layout of the GUI
    layout = [
        [sg.Text("Select a folder:")],
        [sg.Input(key="-FOLDER-"), sg.FolderBrowse()],
        [sg.Button("OK"), sg.Button("Cancel")]
    ]

    # Create the window
    window = sg.Window("Browser Test", layout)

    # Event loop
    while True:
        event, values = window.read()
        if event == sg.WINDOW_CLOSED or event == "Cancel":
            break
        elif event == "OK":
            selected_folder = values["-FOLDER-"]
            sg.popup(f"Folder selected: {selected_folder}")
            break

    # Close the window
    window.close()

# Constants
SCREEN_WIDTH = 1000
SCREEN_HEIGHT = 650
SCREEN_TITLE = "Platformer"


class MyGame(arcade.Window):
    """
    Main application class.
    """

    def __init__(self):

        # Call the parent class and set up the window
        super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)

        arcade.set_background_color(arcade.csscolor.CORNFLOWER_BLUE)

    def setup(self):
        """Set up the game here. Call this function to restart the game."""
        pass

    def on_draw(self):
        """Render the screen."""

        self.clear()
        # Code to draw the screen goes here


def main():
    """Main function"""
    try:
        window = MyGame()
        window.setup()
        arcade.run()
    finally:
        arcade.cleanup_texture_cache()

gui()
main()
gui()
main()
gui()

Resolved with new dev version of arcade