Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to control how a function will be executed in python?

I know python is extremely flexible allowing -almost- anything user wants. However I have never seen nor heard of such a feature, and could not find anything related online: is it possible to execute a variable that is a function step by step?

def example_function():
  print("line 1")
  # stuff
  print("line 2")
  # stuff
  return(3)

def step_by_step_executor(fn):
  while fn.has_next_step():
    print(fn.current_step)
    fn.execute_step()
  return fn.return

step_by_step_executor(example_function) 
# print("line 1")
# line 1
# stuff
# print("line 2")
# line 2
# stuff
# return(3)
# returns 3

I think I can implement something like this using a combination of inspect, exec and maybe __call__, but I am interested to see if there is an already existing name and implementation for this.

Example use cases:

@do_y_instead_of_x
def some_function():
  do stuff
  do x
  do more
some_function()
# does stuff
# does y
# does more

@update_progress_bar_on_loops
def some_other_function():
  do stuff
  for x in range...:
     ...
  do more
some_other_function()
# does stuff
# initializes a progress bar, reports whats going on, does the loop
# does more
like image 846
ozgeneral Avatar asked May 12 '26 18:05

ozgeneral


1 Answers

You can create a Python debugger pdb.Pdb instance and pass to it a custom file-like object that implements the write method to selectively output the code portions of the debugger output, and the readline method to always send to the debugger the n (short for next) command. Since the debugger always outputs the line that returns from a function twice, the second time of which is preceded by a --Return-- line, you can use a flag to avoid outputting the redundant line of return:

import pdb

class PdbHandler:
    def __init__(self):
        self.returning = False

    def write(self, buffer):
        if buffer == '--Return--':
            self.returning = True

        # each line of code is prefixed with a '-> '
        _, *code = buffer.split('\n-> ', 1)
        if code:
            if self.returning:
                self.returning = False
            else:
                print(code[0])

    def readline(self):
        return 'n\n'

    def flush(self):
        pass

def example_function():
    print("line 1")
    print("line 2")
    return (3)

handler = PdbHandler()
print('returns', pdb.Pdb(stdin=handler, stdout=handler).runcall(example_function))

This outputs:

print("line 1")
line 1
print("line 2")
line 2
return (3)
returns 3
like image 65
blhsing Avatar answered May 15 '26 08:05

blhsing



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!