Why does this python code work? - python

I have written a simple python module, it has this code:
_log = logging.getLogger("mymodule")
_started = False
def set_log_level(level):
_log.setLevel(level)
if not _started:
_hdlr = logging.FileHandler('mymodule.log')
When I call set_log_level() program fails because symbol _started is not found. It is normal because global _started is missing in the method. But my question is: symbol _log has the same visibility as _started, so why does this symbol can be found?

I don't think your program fails for the reason you think. There's no need to use the global declaration within a function unless you actually modify that variable. (Otherwise, you'd need to use global for every access of something in that namespace, even calling other functions.)
I'm not sure what actually happens when you run your program - perhaps you could provide a traceback or description of the problem.

Related

In Python, how to access a function-internal inline function (intention: to unit test)?

I have a body of python code that contains inline functions within functions. I'd like to unit test the make_exciting inner function, so I'm trying to figure out how to invoke it directly.
def say_something_exciting(name, phrase):
def make_exciting(phrase):
return phrase + "!"
return "%s says '%s'" % (name, make_exciting(phrase))
Function say_something_exciting is written at the top level of a .py file, and is not inside a class. The py file is in the org.something module. Tried:
Invoking the function directly via org.something.say_something_exciting.make_exciting("Hello") - error: 'function' object has no attribute 'make_exciting'
Inspecting dir(org.something.say_something_exciting) and org.something.say_something_exciting.__dict__ for any paths to traverse, didn't see make_exciting anywhere.
internal_function = org.something.say_something_exciting.__dict__.get('make_exciting'), but internal_function is None.
How can I access (unit test) this inner function? This may suggest what I'm asking isn't possible. I'm generally familiar with unit testing and how to use the unittest module; accessing the function is the problem. If it's not possible, how should I re-write this code to support testing (if other than promote the inner function to a top-level function)?. Thanks!
UPDATE: In Java I often give class methods default/package visibility so they're less visible but still accessible to unit tests, looking for a python equivalent.
I don't think you can.
You'll need to return the inner function, or bind it elsewhere. It gets ugly though. You can bind the declared function to somewhere else, from inside the function:
import testmodule
testmodule.testfunc = make_exciting
Or you can return it, for example when a keyword-argument is given, such as export=True.

How to get the name of the module, calling a specific function, in Python.

Is there a way to find out which file is calling a function? (similar to os.path.basename(__file__))
Program structure:
module contains function in question
Somewhere else in the program:
import modulex as mx
mx.function(arg1,arg2)
I need a universal function to tell me what file 'somewhere else in the program' is.
You can try traceback module:
import traceback
currentStack=traceback.extract_stack()
currentStack variable will hold list of file names from where current code is called.
If you have behaviour that depends on the file calling the function, maybe you should pass an extra argument to the function, indicating it?
In python, explicit solutions are considered the best - having behaviour that depends on the caller is not explicit.
If you really have good reasons to need this, you may want to look into the traceback module

How to solve 'global name not defined' with exec python

I have this code that is throwing an error with exec, and I cant get it to work. It works when
not in a function, though
def hashCheck(data):
exec("hashes = {'hi':'hi'}") #it was a file import before
print(hashes['hi']) #right here is error
try:
return(hashes[data]) #and here is also error
except KeyError:
import hashlib
m = hashlib.md5()
m.update(data)
return(m.hexdigest())
Because your function has no assignments to hashes, python assumes when compiling it that hashes is a global variable. However, when compiling the string for exec, you do have an assignment to hashes so python assumes it is a local variable. So your exec statement assigns to a variable in the local scope, but your print statement looks for it in the global scope.
It may work if you change it to something like:
def hashCheck(data):
hashes = None
exec("hashes = {'hi':'hi'}")
print(hashes['hi'])
That said, you probably shouldn't be using exec() unless you really know what you're doing and are sure you need it. If you just want some human-readable serialization for simple python objects, you may want to look into something like yaml instead.

an error in function definition won't be detected in Python?

Here is a python module,
#a.py
def bar():
print x #x not defined, apparently will result in an error
def foo():
pass
if __name__ == '__main__':
foo()
The above module can be run ($ python a.py) without any error. Why? Just because bar is not used in __main__?
But bar's definition is executed, isn't it?
Yes, bar's definition is executed, but the definition doesn't contain an error. It is valid Python to define a function that refers to globals that don't yet exist, so long as they exist when the function is called. Consider this:
def bar():
print x
x = 10
if __name__ == '__main__':
bar()
This does not result in an error. And this is only sensible, since even if x exists at the time the function is defined, there is nothing to stop you using del on it later. The point when x needs to be defined is when bar is called (if ever), not when bar is defined.
If Python did work the way you are suggesting, then it would be impossible to define mutually recursive functions without weird hacks like temporarily binding one name to None, then defining both functions.
EDIT: To elaborate on Ignacio's answer to the Alcott's question in the comments, yes syntax errors are caught before the function can be executed, but they're actually caught before it can be defined either.
When Python loads a file, it parses the entire contents into statements and then executes the statements one at a time. A syntax error means it was unable to successfully figure out what statements the file contains, so it can't execute anything. So the error will occur when the file is loaded, which means either when you directly run it with the interpreter, or when you import it.
This pre-processing step is known as "compile time", even though Python is not normally thought of as a compiled language; it is technically compiled to a byte code format, but this is almost entirely uninteresting because the byte code pretty much just directly represents the source code statements.
Python resolves name lookups at runtime.
def bar():
print x
x = 3
bar()
It's true that the definition of bar is executed when you run the script. However, Python can't determine whether a global variable named x actually exists until the whole script is run.
For example, you could do:
if __name__ == '__main__':
if random.random() < 0.5:
x = 5
foo()
The compiler wouldn't be able to determine at compile time whether x is going to exist or not.

Declare function at end of file in Python [duplicate]

This question already has answers here:
How do I forward-declare a function to avoid `NameError`s for functions defined later?
(17 answers)
Closed 8 months ago.
Is it possible to call a function without first fully defining it? When attempting this I get the error: "function_name is not defined". I am coming from a C++ background so this issue stumps me.
Declaring the function before works:
def Kerma():
return "energy / mass"
print Kerma()
However, attempting to call the function without first defining it gives trouble:
print Kerma()
def Kerma():
return "energy / mass"
In C++, you can declare a function after the call once you place its header before it.
Am I missing something here?
One way that is sort of idiomatic in Python is writing:
def main():
print Kerma()
def Kerma():
return "energy / mass"
if __name__ == '__main__':
main()
This allows you to write you code in the order you like as long as you keep calling the function main at the end.
When a Python module (.py file) is run, the top level statements in it are executed in the order they appear, from top to bottom (beginning to end). This means you can't reference something until you've defined it. For example the following will generate the error shown:
c = a + b # -> NameError: name 'a' is not defined
a = 13
b = 17
Unlike with many other languages, def and class statements are executable in Python—not just declarative—so you can't reference either a or b until that happens and they're defined. This is why your first example has trouble—you're referencing the Kerma() function before its def statement has executed and body have been processed and the resulting function object bound to the function's name, so it's not defined at that point in the script.
Programs in languages like C++ are usually preprocessed before being run and during this compilation stage the entire program and any #include files it refers to are read and processed all at once. Unlike Python, this language features declarative statements which allow the name and calling sequence of functions (or static type of variables) to be declared (but not defined), before use so that when the compiler encounters their name it has enough information to check their usage, which primarily entails type checking and type conversions, none of which requires their actual contents or code bodies to have been defined yet.
This isn't possible in Python, but quite frankly you will soon find you don't need it at all. The Pythonic way to write code is to divide your program into modules that define classes and functions, and a single "main module" that imports all the others and runs.
For simple throw-away scripts get used to placing the "executable portion" at the end, or better yet, learn to use an interactive Python shell.
If you are willing to be like C++ and use everything inside a functions. you can call the first function from the bottom of the file, like this:
def main():
print("I'm in main")
#calling a although it is in the bottom
a()
def b():
print("I'm in b")
def a():
print("I'm in a")
b()
main()
That way python is first 'reading' the whole file and just then starting the execution
Python is a dynamic programming language and the interpreter always takes the state of the variables (functions,...) as they are at the moment of calling them. You could even redefine the functions in some if-blocks and call them each time differently. That's why you have to define them before calling them.

Categories

Resources