Python 3 function import error - python

I am new to python please suggest me the solution
I have two python files first is imtest.py as follows:
d = dict()
if __name__ == '__main__':
def salry(a):
d["f"] = a
print (d)
second is testim.py as follows:
import imtest
a= 90
b = 200
imtest.salry(a)
imtest.salry(b)
When I am trying to run testim.py, it's giving error as :
AttributeError: module 'imtest' has no attribute 'salry'
Then I have modified second file testim.py as follows:
from imtest import salry
a= 90
b = 200
salry(a)
salry(b)
Now I am getting error as
ImportError: cannot import name 'salry'
What could be the error why I am not able to import that function?

The __name__ magic variable has different value depending on whether the module is executed as a script (python imtest.py) or imported from another module. In the first case, __name__ is set to "__main__", in the second case it gets the module's name ("imtest" in your case). The result is that everything in the if __name__ == "__main__": block is only executed when using imtest.py as a script. When you import it from testim.py this part is not executed, so the def salry statement is not executed, so the function is not defined, so you cannot import it.
The solution is quite obvious: put the function definition outside this block:
d = dict()
def salry(a):
d["f"] = a
if __name__ == '__main__':
print (d)

If you want your salary function to be available to other modules, it needs to be in outer scope, so:
d = dict()
def salry(a):
d["f"] = a
print (d)

Instead of this you have to this
d = dict()
def salry(a):
d["f"] = a
print(d)
now you can use it as
from imtest import salry
Now it works fine

Your imtest.py file is imported in your testim.py file, it's not the file that you're running. So it's not your main file, therefore the condition (name == 'main') will be false, and the salry function won't be defined.
You must remove the if statement:
d = dict()
def salry(a):
d["f"] = a
print (d)

Related

Spyder - NameError: name 'variable' is not defined with vars(), but gobals works

I am creating dynamic variables with:
import mplfinance as mpf
import pandas as pd
from polygon import RESTClient
def main():
with RESTClient('key') as client:
start = "2019-02-01"
end = "2019-02-02"
ticker = "TVIX"
intervals = [5,15,30,60]
for i in intervals:
print(f'downloading {i} minutes.')
vars()[f'df{i}'] = client.stocks_equities_aggregates(ticker, str(i), "minute", start, end, unadjusted=False)
print(df5)
if __name__ == '__main__':
main()
When running I get the error NameError: name 'df5' is not defined.
I can debug and see the variable does exist under Spyder variable explorer as below.
It works for global() but not vars() what am I doing wrong please?
I've done some testing with a simplified version of your code. After some searching online it's not clear to me where you got that idea that you can create a new variable by simply adding an entry to the locals() dict. It does appear to work when adding to the globals() dict:
import pprint
def main():
pp = pprint.PrettyPrinter(indent=4)
intervals = [5,15,30,60]
for i in intervals:
print(f'i = {i}')
vars()[f'df{i}'] = i**3
# if i == 5:
# print('i==5: df5=',df5)
globals()[f'df{i}'] = i**3
if i == 5:
print('i==5: df5=',df5)
print('vars()=')
pp.pprint(vars())
print('globals()=')
pp.pprint(globals())
print('df5=')
print(df5)
if __name__ == '__main__':
main()
If you run the above code, it works. But if you uncomment the lines:
if i == 5:
print('i==5: df5=',df5)
You will see that even in the namespace of the loop, the variable df5 is not defined. Apparently this idiom of dynamically creating a new symbolic name with locals() does not work.

want to use the variable in this file not in the import one

Hey guys here is the problem that I have faced in my project. Here I use a simple example to explain it. When I try to run the main.py, I want to use the variable in this module not in the helper, but the output result is always 2 even when i delete the global variable "a". Is there any way without inputting the function argument? Hope someone can help :(
helper.py
a = 2
def test():
print(a)
main.py
from helper import *
del globals()["a"]
if __init__ == "__main__":
a = 10
test()
You could just modify the attribute:
main.py
import helper
if __name__ == "__main__":
helper.a = 10
helper.test()
Output:
10
Edit:
You could try:
helper.py
a = [2]
def test():
print(a[0])
main.py
from helper import *
if __name__ == "__main__":
a.clear()
a.append(10)
test()
Output:
10

How can I access the name a module was imported as?

I want to write a simple tutorial in my Python module foo.
If the module is imported as foo I would like the tutorial to call it foo:
>>> import foo
>>> foo.tutorial()
Please run foo.baz().
However, when the module is imported as bar - I want the tutorial to call it bar:
>>> import foo as bar
>>> bar.tutorial()
Please run bar.baz().
I know that neither __name__ nor __package__ variables would change their value on import ... as ....
To be different from Is it possible to detect way of import of a module in python? - it will be enough for me to know the first alias the module is imported with.
It's not pretty, foolproof, or production worthy, but:
import inspect
import sys
thismod = sys.modules[__name__]
def imported_as():
imported_frame = inspect.currentframe().f_back.f_back
for k, v in imported_frame.f_locals.items():
if v is thismod:
return k
for k, v in imported_frame.f_globals.items():
if v is thismod:
return k
def tutorial():
print('please call {}.baz()'.format(imported_as()))
A tiny explanation:
jump up two stack frames
look at the locals and globals to find the module object that is identical to the module
Why you should really never do this:
it isn't foolproof:
from imports will break this
multiple imports of the same module will nondeterministically give only the first found name
inspect.currentframe is super magical and should generally be avoided in production code
Here is a similar solution to Anthony's. I believe it better handles multiple imports. from imports are still an issue.
import inspect
import re
import readline
def tutorial():
frame = inspect.currentframe().f_back
if "__file__" in frame.f_locals:
f = inspect.getframeinfo(frame)
m = re.search(r"(([^\.]*).*)\.tutorial", f.code_context[0].strip())
if m:
parent,path = m.group(2),m.group(1)
if inspect.ismodule(frame.f_locals[parent]):
print "Please run {}.baz()".format(path)
return
print "Verify import and run foo.baz()"
else:
loc = frame.f_locals
glo = frame.f_globals
local_foo = [(k, v.__name__)for k,v in loc.items() if inspect.ismodule(v) and v.__name__=="foo"]
global_foo = [(k, v.__name__)for k,v in glo.items() if inspect.ismodule(v) and v.__name__=="foo"]
if local_foo and set(local_foo)==set(global_foo):
print "Please run {}.baz()".format(global_foo[-1][0])
elif local_foo and global_foo:
print "Please run {}.baz() in local scope or {}.baz()".format(local_foo[-1][0], global_foo[-1][0])
elif local_foo:
print "Please run {}.baz() in local scope".format(local_foo[-1][0])
elif global_foo:
print "Please run {}.baz()".format(global_foo[-1][0])
else:
n = readline.get_current_history_length()
h = [str(readline.get_history_item(i)) for i in range(n)] + [readline.get_line_buffer()]
h.reverse()
for i in h:
matches = re.findall(r"([A-Za-z0-9_-]*(\.[A-Za-z0-9_-]*)*)\.tutorial", i)
for match in matches:
if _baz_check(glo, match[0]):
print "Please run {}.baz()".format(match[0])
return
print "Verify import and run foo.baz()"
def _baz_check(d, path):
path = path.split(".")
if path[0] not in d:
return False
cur = d[path[0]]
for i in range(1,len(path)):
if not hasattr(cur, path[i]):
return False
cur = getattr(cur, path[i])
return hasattr(cur, "__name__") and cur.__name__ == "foo" and hasattr(cur, "baz")
def baz():
print "Baz"
import foo
foo.tutorial()
import foo as bar
bar.tutorial()
def f():
import foo as local_foo
local_foo.tutorial()
f()
from foo import tutorial
tutorial()
import mod
mod.foo.tutorial()
from mod import foo as dum
dum.tutorial()
Please run foo.baz()
Please run bar.baz()
Please run local_foo.baz()
Verify import and run foo.baz()
Please run mod.foo.baz()
Please run dum.baz()

Testing students' code in Jupyter with a unittest

I'd like my students to be able to check their code as they write it in a Jupyter Notebook by calling a function from an imported module which runs a unittest. This works fine unless the function needs to be checked against objects which are to be picked up in the global scope of the Notebook.
Here's my check_test module:
import unittest
from IPython.display import Markdown, display
def printmd(string):
display(Markdown(string))
class Tests(unittest.TestCase):
def check_add_2(self, add_2):
val = 5
self.assertAlmostEqual(add_2(val), 7)
def check_add_n(self, add_n):
n = 6
val = 5
self.assertAlmostEqual(add_n(val), 11)
check = Tests()
def run_check(check_name, func, hint=False):
try:
getattr(check, check_name)(func)
except check.failureException as e:
printmd('**<span style="color: red;">FAILED</span>**')
if hint:
print('Hint:', e)
return
printmd('**<span style="color: green;">PASSED</span>**')
If the Notebook is:
In [1]: def add_2(val):
return val + 2
In [2]: def add_n(val):
return val + n
In [3]: import test_checks
In [4]: test_checks.run_check('check_add_2', add_2)
PASSED
In [5]: test_checks.run_check('check_add_n', add_n)
!!! ERROR !!!
The error here is not suprising: add_n doesn't know about the n I defined in check_add_n.
So I got to thinking I could do something like:
In [6]: def add_n(val, default_n=None):
if default_n:
n = default_n
return val + n
in the Notebook, and then passing n in the test:
def check_add_n(self, add_n):
val = 5
self.assertAlmostEqual(add_n(val, 6), 11)
But this is causing me UnboundLocalError headaches down the line because of the assignment of n, even within an if clause: this is apparently stopping the Notebook from picking up n in global scope when it's needed.
For the avoidance of doubt, I don't want insist that n is passed as an argument to add_n: there could be many such objects used but not changed by the function being tested and I want them resolved in the outer scope.
Any ideas how to go about this?
You can import __main__ to access the notebook scope:
import unittest
from IPython.display import Markdown, display
import __main__
def printmd(string):
display(Markdown(string))
class Tests(unittest.TestCase):
def check_add_2(self, add_2):
val = 5
self.assertAlmostEqual(add_2(val), 7)
def check_add_n(self, add_n):
__main__.n = 6
val = 5
self.assertAlmostEqual(add_n(val), 11)
check = Tests()
def run_check(check_name, func, hint=False):
try:
getattr(check, check_name)(func)
except check.failureException as e:
printmd('**<span style="color: red;">FAILED</span>**')
if hint:
print('Hint:', e)
return
printmd('**<span style="color: green;">PASSED</span>**')
This gives me a PASSED output.
This works because when you execute a python file that file is stored in sys.modules as the __main__ module. This is precisely why the if __name__ == '__main__': idiom is used. It is possible to import such module and since it is already in the module cache it will not re-execute it or anything.

python memcache search string

any idea how i can search a string in memcache,i have a list of domains which are loaded onto memcache
what i would like to do is search a string on those domains...
[root#server python]# cat memtest.py
#!/usr/bin/env python
import os
import sys
import memcache
domain = "http://www.yahoo.com/images.txt"
s = memcache.Client(["127.0.0.1:11211"])
def addData():
proc = open("domains.txt","r")
for i in proc.readlines():
d = i.rstrip("\n");
s.set(d,1)
def getData():
name = s.get("yahoo.com")
print name
name = s.get("xaa.com")
print name
##dummy code, just an example
if domain in s.get(domain):
print found
def main():
addData()
getData()
if __name__ == "__main__":
main()
def addData():
proc = open("domains.txt","r")
for i in proc.readlines():
d = i.rstrip("\n");
s.set(d,d)
def getData():
name = s.get("yahoo.com")
print name
name = s.get("xaa.com")
print name
##dummy code, just an example
if s.get("yahoo.com"):
if domain.find(s.get("yahoo.com")) > 0:
print found
To retrieve a value from memcache, you have to know the exact key under which the value was stored.
s.get("yahoo.com")
will work only if
s.set("yahoo.com", <some value>)
was executed before.
looks like you don't know the exact keys because they're being retrieved from a file.
You can try using a regular expression to get the base domain from the file, and make sure "yahoo.com" is used as a key.

Categories

Resources