Load one function but cannot load another in Python - python

I have a Python file with two functions in it:
== bar.py ==
def foo1(): pass
def foo2(): pass
== EOF ==
And then I import it into the global namespace like so:
from bar import *
So both functions foo1 and foo2 should be available to me. If I try to print each one:
print(foo1)
then the interpreter happily tells me it's there:
<function foo1 at 0x7fd6e489fcf8>
But then I try to print the second one:
print(foo2)
And I get the error:
NameError: name 'foo2' is not defined
What are some possible causes of this? Could this be, for example, if foo1 was written in Python 3 syntax and foo2 was written in Python 2 syntax? What else could it be?
NOTE: thanks to this question, which I used for formatting this question.
EDIT: Here's another version of bar.py, as requested in a comment:
def foo1():
pass
def foo2():
pass

This might occur if another version of bar.py exists in a filesystem path that is listed in your PYTHONPATH before the bar.py you are actually editing. The python interpreter will use the first bar.py it finds in the python path, after the current working folder of course.

Related

Python how to use function in imported file defined in importing file?

Sometimes, I see examples like this, but I don't understand how do they work. Imported module uses function without any places in which this function is set to use. Please can someone explain me how to use them.
Example:
from some_package import *
def some_func():
# do_something
pass
imported_func()
And then imported_func somehow defines some_func and uses it. How is this implemented?
When I tried to call some_func from module.py I received an error. Again: idea is to use function from imported file which was defined in importing file. I couldn't find answer in google.
I tried:
from f.module import *
obj = cls()
def some_func():
for _ in range(100):
print("smth")
obj.imported_func()
Code in main.py
class cls:
#staticmethod
def imported_func():
some_func()
Code in module.py
I have main.py and folder f in one directory. In folder f I have module.py
The way to do this is at first import __main__ then call __main__.some_func(), but remember, it's not a good practice because at least you are reserving name, what can become common reason for errors.

Python design pattern

I have a module that does something one of two ways:
project/
|-- main.py
+-- module.py
main.py
import module
module.do_something()
module.set_method(module.WAY_2)
module.do_something()
module.py
WAY_1 = "the_first_way"
WAY_2 = "the_second_way"
method = WAY_1 # by default
def set_method(new_method):
method = new_method
def do_something_the_first_way():
print "Doing it the first way"
def do_something_the_second_way():
print "Doing it the second way"
def do_something():
if method == WAY_1:
do_something_the_first_way()
if method == WAY_2:
do_something_the_second_way()
When I run main.py, I get this output:
Doing it the first way
Doing it the first way
It looks like the method variable of module.py is not getting updated, even though we try to set it with set_method from main.py. I have an idea of what's happening here based on this question, but I want to know what the best way to fix the problem is.
What is the most elegant, Pythonic way to solve this problem?
By default, any assignment in a function creates a function-local variable; it does not update a global by the same name. You need to define it as global explicitly:
def set_method(new_method):
global method
method = new_method

how do imports work for a module used as a singleton?

I'm confused about what happens if you tread a module as a singleton.
Say I have a module conf.py, that contains some configuration parameters which need to be accessed by multiple other files. In conf.py, I might have this piece of code (and nothing else):
myOption = 'foo' + 'bar'
If I now import it first in a.py, and then in b.py, my understanding is that the first time it is imported (in a.py), the string concatenation will be executed. But the second time it is imported (in b.py), conf.myOption already has its value, so no string concatenation will be executed. Is this correct?
If after doing these two imports, I then execute the following in b.py
conf.myOption = 'aDifferentFoobar'
then obviously b.py would now see this new value. Would a.py see the same value, or would it still see 'foobar'?
I believe (but correct me if I'm wrong) that imports are always referred to by reference, not by value? And I'm guessing that's what the above questions boil down to.
Try it and see:
mod.py:
def foo():
print("in foo()")
return "foo"
bar = foo()
opt = "initial"
b.py:
import mod
mod.opt = "changed"
a.py:
import mod
import b
print(mod.bar)
print(mod.opt)
Execute a.py:
$ python3.4 a.py
Output:
in foo()
foo
changed
We learn:
foo() is only executed once
mod.opt is changed by b.py
a.py sees the changed value of mod.opt
bonus: the order of imports in a.py does not matter

How to import another external python module?

this is probably a dumb question, but wasnt too sure what else to do.
main.py
import module2
global x
hello="Hello"
x=module2.message()
x.say()
module2.py
class message:
def say():
print hello
When I print hello, i am referring to the hello variable in main.py however this method will return an error. Does anyone know the solution? (i would prefer not to pipe the hello variable into the function)
The only reliable solution is called encapsulation.
So, basically, you could change your code to look like that:
main.py
import module2
global x
hello="Hello"
x=module2.message(hello)
x.say()
module2.py
class message:
def __init__(self, hello):
self.hello = hello
def say():
print self.hello
Plus try to follow coding style of Python - life of you and future developers of your code will be easier.
Multiple options, but do note that one module cannot ever access the calling module directly.
Simply pass hello as a variable (def say(msg): print msg)
Pass all variables in main.py to module2: def say(g): print g['hello'] and say(globals())
Store it somewhere, then extract it when you need it.
Since main.py imports module2.py, you can access the globals defined in moule2 in main.
In your case since module2 is not importing main, so the globals in main is not accessed in module2.
one solution is that defined by #Tadeck
In this particular example, it's totally OK for module2.py to import main.py, there are some gotcha's though.
The most obvious is that main.py is probably being run from the command line, like python main.py, which has the effect of making that file think it's called __main__. You could import that module in module2, but that's sort of unusual; it's called "main.py" and you want to import main. Doing so will cause the module to be imported a second time.
For that to be OK, you have to arrange for importing the file to have no side effects unless it's imported as __main__. A very common idiom in python is to test that condition at the end of a module.
import module2
global x
hello="Hello"
def main():
x=module2.message()
x.say()
if __name__ == '__main__':
main()
And now it's just fine for module2.py to actually import main. On the other hand, importing variables from one module into another gets hard to predict when the imports can be recursive, you may not have that variable yet because the module is already trying to import you. On the other hand, it's always safe to refer to a variable in a module using dotted syntax. So your module2.py should be:
import main
class message:
def say():
print main.hello
which also makes it more obvious just where hello came from.

How to find where a function was imported from in Python?

I have a Python module with a function in it:
== bar.py ==
def foo(): pass
== EOF ==
And then I import it into the global namespace like so:
from bar import *
So now the function foo is available to me. If I print it:
print foo
The interpreter happily tells me:
<function foo at 0xb7eef10c>
Is there a way for me to find out that function foo came from module bar at this point?
foo.__module__ should return bar
If you need more info, you can get it from sys.modules['bar'], its __file__ and __package__ attributes may be interesting.
Try this:
help(foo.func_name)
Instead of
from bar import *
use
from bar import foo
Using the from ... import * syntax is a bad programming style precisely because it makes it hard to know where elements of your namespace come from.
If you have IPython, you can also use ?:
In[16]: runfile?
Signature: runfile(filename, args=None, wdir=None, is_module=False, global_vars=None)
Docstring:
Run filename
args: command line arguments (string)
wdir: working directory
File: /Applications/PyCharm.app/Contents/helpers/pydev/_pydev_bundle/pydev_umd.py
Type: function
Compare with __module__:
In[17]: runfile.__module__
Out[17]: '_pydev_bundle.pydev_umd'

Categories

Resources