Hi,
My program needs to override a built-in function, and my current solution doesn’t seem to work with Python 3. I found this gist on GitHub, but it was written in Python 2, and __bulitin__
does seem to exist anymore. Is there a way to do this with Python 3?
My current solution:
import __builtin__ # This doesn't seem to exist anymore
def file_exec(path):
with open(path, "r") as f:
exec(f.read())
__builtin__.exec = file_exec
Any help is greatly appreciated!
Update, it looks like __builtin__
for Python3 is builtins
, but after replacing everything correctly, using the overridden function gives the error, TypeError: file_exec() takes 1 positional argument but 2 were given
, but I only supplied it with one argument.
1 Like
Ah. I suspect you’re getting passed self
then. Just add an unused argument as the first parameter. Or maybe the second one is unused, but that’s not typical.
1 Like
Seems to fix that, but now I get TypeError: expected str, bytes or os.PathLike object, not dict
, though I’m not passing anything different into the with open(), the location where the error is occuring.
Odd. Try adding a print statement into it to print both of its parameters for troubleshooting so we can see what it’s doing.
1 Like
So currently, this is my code. Is this what you meant?
Edit: Nevermind I misunderstood
import builtins
def file_exec(randomParameter, path):
print(f"{randomParameter} {path}")
with open(path, "r") as f:
exec(f.read())
builtins.exec = file_exec
exec("randomArg", "file.py")
No, I meant something like this:
import builtins
def file_exec(unused, file):
print(f"""1. {unused}
2. {file}""")
with open(path, "r") as f:
exec(f.read())
builtins.exec = file_exec
exec("file.py")
Assuming your code only passes a file name to the call, I think this should print whatever python is doing.
Also, that’s going to cause a recursive call I think, probably do this:
bkpExec = exec
# stuff goes here
bkpExex(f.read())
# Other stuff.
2 Likes
Ok, before we continue, I should probably provide a bit of background information I realized I should have provided earlier. Currently, the file_exec command is being imported from another file, and so is a function for reading files, but I’d assume everything would work the same. I’ll link the full error below.
Full Error
Traceback (most recent call last):
File "src/boot.py", line 22, in <module>
exec("a", "install.py")
File "/home/runner/pyos3/src/func/util.py", line 5, in file_exec
exec(read_file(path))
File "/home/runner/pyos3/src/func/file.py", line 7, in read_file
with open(path, "r") as file:
FileNotFoundError: [Errno 2] No such file or directory: 'install.py'
Failed calling sys.__interactivehook__
Traceback (most recent call last):
File "/nix/store/hd4cc9rh83j291r5539hkf6qd8lgiikb-python3-3.10.8/lib/python3.10/site.py", line 447, in register_readline
import rlcompleter
File "/home/runner/pyos3/src/func/util.py", line 5, in file_exec
exec(read_file(path))
File "/home/runner/pyos3/src/func/file.py", line 7, in read_file
with open(path, "r") as file:
TypeError: expected str, bytes or os.PathLike object, not dict
Will do, its a bit of a mess currently so let me know if anything is confusing.
https://replit.com/@bobbypac/pyos3
Hm. Try flipping the file name and argument parameters.
1 Like
No luck, it still results in the same error.
1 Like
Huh. Try the printer mentioned earlier:
Attempted edit to make it work in your code’s context:
def file_exec(randomArg, path):
print(f"""1. {randomArg}
2. {path}""")
exec(read_file(path))
Well, I think I know why its flaring up now,
Output:
1. <code object <module> at 0x7f1ec60dd6e0, file "/nix/store/hd4cc9rh83j291r5539hkf6qd8lgiikb-python3-3.10.8/lib/python3.10/rlcompleter.py", line 1>
2. {'__name__': 'rlcompleter', '__doc__': None, '__package__': '', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f1ec60a2b90>, '__spec__': ModuleSpec(name='rlcompleter', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7f1ec60a2b90>, origin='/nix/store/hd4cc9rh83j291r5539hkf6qd8lgiikb-python3-3.10.8/lib/python3.10/rlcompleter.py'), '__file__': '/nix/store/hd4cc9rh83j291r5539hkf6qd8lgiikb-python3-3.10.8/lib/python3.10/rlcompleter.py', '__cached__': '/nix/store/hd4cc9rh83j291r5539hkf6qd8lgiikb-python3-3.10.8/lib/python3.10/__pycache__/rlcompleter.cpython-310.pyc'}
Adjusted it a bit for readability
That’s um. Certainly not what we were trying to pass, lol. Where was it called?
Called it in src/boot.py, where I overrid Python’s default exec()
.
Hm. Off chance, but try changing util.py
to:
from func.file import read_file
import builtins
backupExec = builtins.exec
def file_exec(randomArg, path):
print(f"""1. {randomArg}
2. {path}""")
backupExec(read_file(path))
Still no luck, this might be a bit far-fetched. Honestly, I’m not really sure why I even have to override it in the first place.
Instead of overriding the builtin, try just overriding exec itself?
Example:
builtins.exec = file_exec
# To
exec = file_exec
1 Like
It seems to want a dictionary now.
Traceback (most recent call last):
File "src/boot.py", line 20, in <module>
exec("a", "install.py")
TypeError: exec() globals must be a dict, not str