2

Full disclosure, I am completely new to programming so I apologize in advance. I am working on this python script that will get user input and use that input in certain OS commands (ping, traceroute, whois). It is not complete but here is the script :

#!/usr/bin/python

from os import system

def pingz():

    system('ping -c 5 %(ab)s' % locals())

def trace_route():

    system('traceroute %(cd)s' % locals())

print("My Web Utility:")

print("____________________\n")

print(" 1)Ping a website/IP Address.\n")

print(" 2)Trace the route to a website/IP Address.\n")

print(" 3)Whois inforation.\n")

choice = raw_input("What would you like to do? \n")

if choice == '1':

    ab = raw_input("Please enter the Domain Name/IP Address:\n")

    pingz()

elif choice == '2':

    cd = raw_input("Please enter the Domain Name/IP Address:\n")

    trace_route() 

I'm getting two errors on each "choice". So for example if I type 1 I get a prompt asking for the domain name/ip address and when I enter it, the error I get is :

Traceback (most recent call last):
File "./test2.py", line 19, in <module>
pingz()
File "./test2.py", line 6, in pingz
system('ping -c 5 %(ab)s' % locals())
KeyError: 'ab'

And very similar error for choice 2. Is there something wrong with how I'm calling the function? Can anyone point me in the right direction please? I've tried smaller implementations of this script (without making my own functions) and no else/elif statements and it works fine... Sorry for the long post and thanks in advance!

1
  • you need to use globals() Commented May 5, 2016 at 6:49

2 Answers 2

2

locals refers to current frame, which does not have ab defined in it. It's inside your globals(),

You can access it like this:

def pingz():
    system('ping -c 5 %(ab)s' % globals())
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so much for the explanation, definitely fixed the problem!! :)
1

You don't have any local variables inside the functions, so locals() is an empty dictionary, therefore it raises a KeyError.

Instead of relying on locals() (or globals() for that matter) you should simply pass the variable to the function:

def pingz(host):
    system('ping -c 5 %s' % host)

.
.
.

ab = raw_input("Please enter the Domain Name/IP Address:\n")

pingz(ab)

The method is preferable compared to the use of locals() or globals(). It's more readable, clearer and less prone to mistakes, especially if you are planning to modify a mutable object inside the function.

Also, as both globals and locals are essentialy dictionaries, they force you to use unique variable names, and there is no reason that 2 functions should have unique names for their local variables (for example, both your ping and traceroute functions should have a variable called host).

3 Comments

Awesome, this solution also worked, thanks! Is there a reason it is preferable over something like globals()? Is it a tiny bit faster? Just curious :)
It sure isn't faster (if anything, it would be a tiny bit slower). The reason it is preferred is it's more readable, clearer and less prone to mistakes. Also, as both globals and locals are essentialy dictionaries, they force you to use unique variable names, and there is no reason that 2 functions should have unique names for their local variables (for example, both your ping and traceroute function should have a variable called host).
Oh, I get it! Thanks for the information man, I really appreciate it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.