Vadim  K
Vadim K

Reputation: 129

Python: good way to pass variable to multiple function calls

Need a help with the next situation. I want to implement debug mode in my script through printing small completion report in functions with command executed name and ellapsed time like:

def cmd_exec(cmd):
    if isDebug:
        commandStart = datetime.datetime.now()
        print commandStart
        print cmd
    ...
    ... exucuting commands
    ...
    if isDebug:
        print datetime.datetime.now() - command_start
    return

def main():
    ...
    if args.debug:
        isDebug = True
    ...
    cmd_exec(cmd1)
    ...
    cmd_exec(cmd2)
    ...

How can isDebug variable be simply passed to functions? Should I use "global isDebug"?

Because

    ...
    cmd_exec(cmd1, isDebug)
    ...
    cmd_exec(cmd2, isDebug)
    ...

looks pretty bad. Please help me find more elegant way.

Upvotes: 3

Views: 378

Answers (4)

Mark Ransom
Mark Ransom

Reputation: 308452

You can use a module to create variables that are shared. This is better than a global because it only affects code that is specifically looking for the variable, it doesn't pollute the global namespace. It also lets you define something without your main module needing to know about it.

This works because modules are shared objects in Python. Every import gets back a reference to the same object, and modifications to the contents of that module get shared immediately, just like a global would.

my_debug.py:

isDebug = false

main.py:

import my_debug

def cmd_exec(cmd):
    if my_debug.isDebug:
        # ...

def main():
    # ...
    if args.debug:
        my_debug.isDebug = True

Upvotes: 1

JL Peyret
JL Peyret

Reputation: 12204

Specifically for this, I would use partials/currying, basically pre-filling a variable.

import sys
from functools import partial
import datetime

def _cmd_exec(cmd, isDebug=False):
    if isDebug:
        command_start = datetime.datetime.now()
        print command_start
        print cmd

    else:
        print 'isDebug is false' + cmd

    if isDebug:
        print datetime.datetime.now() - command_start
    return

#default, keeping it as is...
cmd_exec = _cmd_exec

#switch to debug
def debug_on():
    global cmd_exec

    #pre-apply the isDebug optional param
    cmd_exec = partial(_cmd_exec, isDebug=True)


def main():
    if "-d" in sys.argv:
        debug_on()

    cmd_exec("cmd1")
    cmd_exec("cmd2")

main()

In this case, I check for -d on the command line to turn on debug mode and I do pre-populate isDebug on the function call by creating a new function with isDebug = True.

I think even other modules will see this modified cmd_exec, because I replaced the function at the module level.

output:

jluc@explore$ py test_so64.py
isDebug is falsecmd1 isDebug is falsecmd2

jluc@explore$ py test_so64.py -d
2016-10-13 17:00:33.523016 cmd1 0:00:00.000682 2016-10-13 17:00:33.523715 cmd2 0:00:00.000009

Upvotes: 0

brianpck
brianpck

Reputation: 8254

Python has a built-in __debug__ variable that could be useful.

if __debug__:
    print 'information...'

When you run your program as python test.py, __debug__ is True. If you run it as python -O test.py, it will be False.

Another option which I do in my projects is set a global DEBUG var at the beginning of the file, after importing:

DEBUG = True

You can then reference this DEBUG var in the scope of the function.

Upvotes: 2

chepner
chepner

Reputation: 532053

isDebug is state that applies to the application of a function cmd_exec. Sounds like a use-case for a class to me.

class CommandExecutor(object):

    def __init__(self, debug):
        self.debug = debug

    def execute(self, cmd):
        if self.debug:
            commandStart = datetime.datetime.now()
            print commandStart
            print cmd
        ...
        ... executing commands
        ...
        if self.debug:
            print datetime.datetime.now() - command_start

def main(args):
    ce = CommandExecutor(args.debug)
    ce.execute(cmd1)
    ce.execute(cmd2)

Upvotes: 2

Related Questions