0

One thing I keep having trouble with in Python is passing information from one function to another, changing it and then passing it back to the original function to usefully use. Take a look at this very basic example, trying to create a ping function that can be called by various other functions.

import subprocess
pingchk = 0

def pinger(pcName, pingchk):
    ping_out = subprocess.Popen(["ping", "-n", "1", pcName],stdout = subprocess.PIPE).communicate()[0]
    if ('unreachable' in ping_out):
        print "Warning", "PC not responding 1."
        pingchk += 1
        return pingchk
    elif ('Request timed out.' in ping_out):
        print "Warning", "PC not responding 2."
        pingchk += 1
        print pingchk
        return pingchk
    elif ('Ping request could not find host' in ping_out):
        print "Warning", "PC not responding 3."
        pingchk += 2
        print pingchk
        return pingchk
    else:
        print "Machine available!"

def someFunction():
    pcName = raw_input("Please enter a pc name: ")
    pinger(pcName, pingchk)
    print pingchk
    if pingchk == 1:
        print "machine not switched on."
    elif pingchk == 2:
        print "machine name not recognized."
    else:
        print "success - machine on."

someFunction()

It's the pingchk bit that I'm struggling with. In this example someFunction is passing the machineName up to pinger to do the work, then I want pinger to pass the result back to someFunction to use. However, someFunction never re-reads the variable pingchk so always reads it as 0.

What do I need to change to pass the results of pinger back to the originating function for use?

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
user3514446
  • 77
  • 3
  • 10
  • 7
    `pingchk = pinger(pcName, pinkchk)`? – jonrsharpe Jun 10 '16 at 13:14
  • @jonrsharpe - thanks for the reply but if I try that it claims that it is being referenced before assignment... – user3514446 Jun 10 '16 at 13:37
  • @jonrsharpe maybe you missed it but `pinger(pcName,` **`pinkchk)`** uses the value of the global variable, by introducing assignment you make it a local variable that is references (as the argument to `pinger`) before it is assigned. – Tadhg McDonald-Jensen Jun 10 '16 at 14:03

4 Answers4

1

As jonrsharpe suggested in a comment the way to go is simply to affect the returned value to the variable:

pingchk = pinger(pcName, pingchk)

There are only 2 caveats here:

  • you have a branch that does not return anything (when you print available) so you will end with a None which may not be what you expect: consistently return 0 in that case or better move the return out of the if:

    def pinger(pcName, pingchk):
        ping_out = subprocess.Popen(["ping", "-n", "1", pcName],stdout = subprocess.PIPE).communicate()[0]
        if ('unreachable' in ping_out):
            print "Warning", "PC not responding 1."
            pingchk += 1
        elif ...
        else:
            print "Machine available!"
        return pingcheck
    
  • as you affect the variable pingcheck in somefunction before is has been used, Python consideres that it is a local variable hiding the global one. You must declare it as global - if you really need it to be global:

    def someFunction():
        global pingchk
        pcName = raw_input("Please enter a pc name: ")
        pingchk = pinger(pcName, pingchk)
    

But if you have no real reason for pingcheck to be global, just let it be local:

    def someFunction():
        pcName = raw_input("Please enter a pc name: ")
        pingchk = pinger(pcName, 0)
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • That's brilliant. Just adding "pingchk = pinger(pcName, 0)" was all I needed. Creating the variable inside the function rather than outside. Thank-you so much! Chris. – user3514446 Jun 10 '16 at 14:47
0

To modify variables inside a function, pass them as list.

def ping(counter):
    counter[0] += 1  # lists are passed by reference, hence they can be changed in place

mycounter = [0]
ping(mycounter)
print mycounter[0]  # this will print 1
ping(mycounter)
print mycounter[0]  # this will print 2
user1308345
  • 1,032
  • 1
  • 8
  • 14
  • Don't use a nuclear weapon to kill a fly... OP's code already return (almost allways...) the new value. jonrsharpe's suggestion is the way to go here – Serge Ballesta Jun 10 '16 at 13:40
0

When you are calling a function in python, it returns a variable just like you are doing a basic math operation. For instance, if you do:

3*2

Your shell will return 6, but doesn't save this result. If you want to save it, just do:

x = 3*2

The same goes for your function pinger, when you call it from someFunction, you have to do:

pingchk = pinger(pcName, pingchk)

As pingchk otherwise is a local variable.

Another remark on your code: in someFunction you first call pinger with pingchk as an argument but it doesn't exist beforehand, therefore, your code won't turn.

ysearka
  • 3,805
  • 5
  • 20
  • 41
0

Two ways:

  1. Use a Global variable - Google will give you plenty of info and examples
  2. My favorite, Put your variable in another module and import it. e.g.

    from commonstuff import pingcheck

Bill M
  • 31
  • 1
  • 3