Question:
I am trying to have it so that a user can run a python file from within a program being run. I am essentially making an operating system for an advanced calculator, and want users to be able to open a python file from the internet. I am getting errors with the exec() builtin function. What am I doing wrong?
#the function that would run the "run program" function
def runEx():
global passWord
runExParam = input('run param:')
passVer = input(userName + '@main @runEX: enter password: ')
if (passVer == passWord):
os.system('clear')
exec(runExParam)
main()
else:
os.system('clear')
print('INVALID PASSWORD...')
print('')
time.sleep(2)
main()
By the way
I don’t actually recommend directly allowing user to use exec in python without checking the code or hiding your codes’ variables and things
People could literally ruin your entire running process by something like
for everything in dir():
del everything
or even your entire file by
with open(__file__, 'w') as f:
pass
So, I personally do NOT recommend using exec directly from prompt
TaokyleYT,
I think in this case it is fine to execute raw user input because, well, it’s supposed to be an OS. If the user bricks the OS, that’s on them.
The first code snippet, with dir(), has no effect.
Also, I checked out your project and… why does it have so many random dunder names?
Hello, there looks to be nothing seriously wrong with your code, but you need to wrap the exec() in a try-except block just in case the code gives an error (including syntax errors).
In addition to this, specify globals as an empty dict, or else the user code will have access to the globals and locals in the current scope.
I should point out quickly that the user chooses a new username and password for each session – this is why I am totally cool with users having access to global variables.
@TaokyleYT I appreciate the info. The program does error out when a user tries running runEx, but to be more clear, runEx runs, but usually the source has a generic syntax error. I am asking the user for an http:// requested python program is sort of the end goal here. Which seems to be the main problem.
Nice. I refactored the code to better handle exceptions:
import traceback
...
def clear():
# Note: this is shell-specific, though you are making an entire os
os.system('clear')
def runEx():
# This function can be refactored in smaller ones
runExParam = input('Enter the URL of the Python file to run:')
passVer = input(userName + '@main @runEX: enter password: ')
clear()
if passVer != passWord:
print('INVALID PASSWORD...')
print()
time.sleep(2)
main()
return
if not runExParam.startswith(('http://', 'https://')):
# \/ consider having custom shell errors for your os
print('error: URL must start with http:// or https://')
try:
response = requests.get(runExParam)
response.raise_for_status()
python_code = response.text
except requests.RequestException as e:
print(f'Error fetching file: {e}')
else:
try:
exec(python_code, {'__name__': '__main__'})
except SystemExit:
pass # you can print exit code
except BaseException:
print(traceback.format_exc())
else:
... # you can print nothing or a message
main()
Also Dave, I would highly recommend to refactor your code to not recursively call main().