1

So I have 2 files, fish_life_simulator.py and menu.py. fish_life_simulator.py is the main file and executes other files like menu.py depending on what happens. So here is the code and how it should work:

import os

os.chdir(os.path.dirname(__file__))

result = exec(open(r'menu.py', encoding='utf-8').read())

print(result)

So at first when the code arrives to result = exec(open(r'menu.py', encoding='utf-8').read()) it executes menu.py and all is fine, but it could stop for several reasons:

  1. The player exit the game
  2. The player entered settings
  3. The player pressed play

So what I decided to do, is when menu.py will stop running it will return a value, like 1, 2 or 3, so I tried several methods that have been included in here: Best way to return a value from a python script like using return or sys.exit("some value here"), but even though I did the part inside of menu.py, neither of them worked, as when I tried return, result from result = exec(open(r'menu.py', encoding='utf-8').read()) always was None for some reason and when I tried sys.exit(1) for example, result didn't get printed at all, so I was just wandering if it was something I was missing inside of fish_life_simulator.py, because the part with sending the value should be fine, but the part of receiving it is problematic.

hellwraiz
  • 359
  • 2
  • 13
  • 7
    You should define functions in your modules, and just call the functions. `exec(open(...).read())` is an anti-pattern. – Barmar May 11 '21 at 22:31
  • 1
    Functions can return values, so it would solve your general problem. – Barmar May 11 '21 at 22:31

2 Answers2

3

Just define a function in menu.py:

def do_stuff_in_menu():
    ...
    return result

and in fish_life_simulator.py you just call that function:

import menu

result = menu.do_stuff_in_menu()
print(result)
schilli
  • 1,700
  • 1
  • 9
  • 17
  • hey... I tried this and I got an error, which says that the module menu doesn't exist. Could it be because the 2 files are in different folders? Or to be exact, I have it like this: ```fish life simulator\fish_life_simulator.py``` and ```fish_life_simulator\other programs\menu.py``` – hellwraiz May 12 '21 at 19:14
  • Add an empty file in `fish_life_simulator\other programs\ ` named `__init__.py`. Python needs these to identify a folder as a module. Otherwise it doesn't look for python modules in that folder. See https://docs.python.org/3/reference/import.html#regular-packages – schilli May 12 '21 at 20:01
  • I... I did that... and I also tried ```os.chdir()``` to make the other programs the central folder, ```sys.path.append``` or ```sys.path.insert```, ```import file``` or ```from file import def```, but it always gives me the same error, ```ModuleNotFoundError: No module named 'menu'``` – hellwraiz May 12 '21 at 20:07
  • oh yeah, and I posted a question about this, so don't worry if you have no idea what's happening in my cacaphony of a code – hellwraiz May 12 '21 at 20:21
  • @hellwraiz I answered your other question, too. – schilli May 12 '21 at 20:57
1

I agree with everyone who says exec() is not the best way to do this, however, since that's not your question, here's an answer for you.

The exec() function always returns None (see docs). If you need the return code, you could use os.system() or one of the various methods from the subprocess library. Unlike exec(), however, both of these alternatives would create a child process.

That said, I personally would not use any of those methods, but would instead modify menu.py to allow you to import it. It's much more natural and direct.

TallChuck
  • 1,725
  • 11
  • 28
  • hey, thanks for the advice! But what do you mean by a child process? Would that mean that I would have to treat them as separate programs if I was to use os.system() instead of import? – hellwraiz May 12 '21 at 19:17
  • you might need to study up on how processes work to understand what's going on. On Linux (I'm not sure of the exact details on Windows, but it's probably similar), the `os.system()` call will `fork()` a new process, and then that new process will run the command given as the argument to `os.system()` using `execv()` or `execve()` (those are Linux system calls, not the same as Python `exec()`). The original (parent) process will sit and wait for the child process to terminate, and the return value of `os.system()` will be the return code of that process – TallChuck May 13 '21 at 16:39