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

Unable to import classes from different files using https://kitao.github.io/pyxel/wasm/launcher/?run= #509

Closed
dComposer opened this issue Dec 23, 2023 · 8 comments

Comments

@dComposer
Copy link

Hi -- I'm trying to use the "https://kitao.github.io/pyxel/wasm/launcher/?run=" command to run a game I just built that's stored in my GitHub repository but it's failing at importing some classes that are stored in different python files. Does the main.py file have to be one giant file for this to work or do I have to explicitly write somewhere that it should look for these import files?

The game I'm trying to run is located here: https://github.com/dComposer/pyxel_breakout
This is the command I'm trying to run: https://kitao.github.io/pyxel/wasm/launcher/?run=dComposer.pyxel_breakout.main

This is the error I'm getting in my web browser:
Traceback (most recent call last):
File "/lib/python311.zip/_pyodide/_base.py", line 499, in eval_code
.run(globals, locals)
^^^^^^^^^^^^^^^^^^^^
File "/lib/python311.zip/_pyodide/_base.py", line 340, in run
coroutine = eval(self.code, globals, locals)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "", line 3, in
File "/lib/python3.11/site-packages/pyxel/cli.py", line 167, in run_python_script
runpy.run_path(python_script_file, run_name="main")
File "", line 291, in run_path
File "", line 98, in _run_module_code
File "", line 88, in _run_code
File "main.py", line 3, in
from ball import Ball
ModuleNotFoundError: No module named 'ball'

Thanks so much!

@BoniLindsley
Copy link

A potential workaround.

# Force download of relative modules from jsdelivr before importing.
for module_path in ("ball.py", "paddle.py"):
    open(module_path).close()

import ball
import paddle

Pyxel tries to download from jsdelivr whenever a missing file in the Pyxel working directory is accessed. This can be triggered by opening the module as a file, so that they are available for import. Not the neatest way to go, but might work. For deeper hierachies using packages, it might be necessary to invalidate the cache first: https://pyodide.org/en/stable/usage/faq.html#why-can-t-i-import-a-file-i-just-wrote-to-the-file-system.

@merwok
Copy link
Contributor

merwok commented Dec 26, 2023

Does that work or is it just an idea?
Kitao uploads files to jsdeliver, but people making games are not adding their module to the same location.

@BoniLindsley
Copy link

Just an idea. Haven't tested it fully.

Another idea can be to download source tarball and extract it. Not something jsdelivr provides, from what I can tell.

@BoniLindsley
Copy link

@dComposer
Copy link
Author

dComposer commented Dec 29, 2023

Thanks for the suggestions, but I'm still getting this ModuleNotFound error:

  File "/lib/python311.zip/_pyodide/_base.py", line 499, in eval_code
    .run(globals, locals)
     ^^^^^^^^^^^^^^^^^^^^
  File "/lib/python311.zip/_pyodide/_base.py", line 340, in run
    coroutine = eval(self.code, globals, locals)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "", line 3, in 
  File "/lib/python3.11/site-packages/pyxel/cli.py", line 167, in run_python_script
    runpy.run_path(python_script_file, run_name="__main__")
  File "", line 291, in run_path
  File "", line 98, in _run_module_code
  File "", line 88, in _run_code
  File "main.py", line 3, in 
    from ball import Ball
ModuleNotFoundError: No module named 'ball'

@BoniLindsley
Copy link

It seems to be fine by the time I have tried iit. If it happens again, you might try purging the jsDelivr CDN cache. https://www.jsdelivr.com/tools/purge. To find the URLs to purge, before clicking to start in the launcher, open up the browser console (usually ctrl+shift+I on Windows or Linux)

Copied 'https://cdn.jsdelivr.net/gh/dComposer/pyxel_breakout/main.py' to '/pyxel_working_directory/main.py' [pyxel.js:209:13]

As for debugging whether this is the issue, the error says that it is trying to import on line 3. But you can see it is not on line 3 anymore https://github.com/dComposer/pyxel_breakout/blob/cbd0b91f5ce619daf54646e31b1de6c41403eb34/main.py

  File "main.py", line 3, in 
    from ball import Ball

So this suggests the old main.py script was still being used.

@kitao
Copy link
Owner

kitao commented Oct 13, 2024

In the web version of Pyxel, when there is a file loading operation (such as fopen), if the file does not exist in the web's local storage, Pyxel replaces it with a file download process. This allows asset files to be loaded even on the web.

However, due to the limitations of the web specifications, it is not possible to retrieve file listings or directory information from the server. Unfortunately, there is no alternative method to replace Python's import statement, which results in the inability to import local files or directories using the run command. (I've tried various approaches, but haven't found a workable solution as of now.)

For the .pyxapp format, a single .pyxapp file is downloaded and unpacked in the web's local storage, so this limitation does not apply. Therefore, if your Python code spans multiple files, I recommend converting it to the .pyxapp format.

I have also added a note about this in the documentation.

@kitao
Copy link
Owner

kitao commented Oct 20, 2024

I would like to consider this as a specification until we find a better solution.

@kitao kitao closed this as completed Oct 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants