I want to call a function inside of an other module but i i always get the same error statement "module 'mat_import' has no attribute 'matread'".
After getting the "filename" and "button_pressed" value from the GUI I want to call matread inside of mat_import. The result should be that I have filename1 and button_pressed accessable inside of the main.py.
The main.py:
EDIT:To get "filename1" and "button_pressed" the function gui inside of GUI.py is called. This works and returns the filename to the main.py. After that i want to call matread inside of mat_import. The function matread should get the filename from the main.py and read the file. The outputs are the two variables "signals" and "signaldata".
import mat_import as mi
import GUI
filename1, button_pressed = GUI.gui()
if (button_pressed ==1):
signals, signaldata = mi.matread
The mat_import.py:
import h5py
import numpy as np
import csv
import os
import main
filename1 = ""
global matread
def matread():
#get signals and signaldata
return signals, signaldata
As mentioned in my comment, my best guess from your description of the problem and the indentation in your question is that matread() is defined within another function in the mat_import.py file. In order to make matread callable from main.py, you need to 1. define it as global and 2. execute the function that it is defined in. Alternatively, you can define matread() outside any other function, as I did with matread2 below. You can read more about variable scope here: https://matthew-brett.github.io/teaching/global_scope.html
mat_import.py:
def matread2():
return "b"
def outer_func():
global matread
def matread(): return "a"
main.py:
import mat_import as mi
try:
mi.matread()
except AttributeError as e:
print(e)
mi.outer_func()
print mi.matread()
print mi.matread2()
Related
I have two python files main.py and conftest.py. I want to access a variable of a method of the class Test declared in main.py from a function declared in conftest.py.
I have tried a bit, but I know it's wrong as I get a syntax error in the first place. Is there any way to do this?
main.py
class Test():
def test_setup(self):
#make new directory for downloads
new_dir = r"D:\Selenium\Insights\timestamp}".format(timestamp=datetime.now().strftime('%Y-%m-%d_%H-%M-%S'))
# print(new_dir)
if not os.path.exists(new_dir):
os.makedirs(new_dir)
saved_dir=new_dir
conftest.py
from main import Test
def newfunc():
dir=Test.test_setup()
print(dir.saved_dir)
There are some errors in your code, but essentially, to access to the variable saved_dir you have to define it as an attribute of the class Test, and after that instantiate an object of that class.
In your code saved_dir is a local variable of the method test_setup so is not visible outside of that context.
I show you the 2 possible correct files:
File main.py
from datetime import datetime
import os
class Test():
def __init__(self):
self.new_dir = ""
self.saved_dir = ""
def test_setup(self):
#make new directory for downloads
#new_dir = r"D:\Selenium\Insights\timestamp}".format(timestamp=datetime.now().strftime('%Y-%m-%d_%H-%M-%S'))
timestamp=datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
self.new_dir = "/home/frank/Selenium/Insights/timestamp/" + timestamp
# print(new_dir)
if not os.path.exists(self.new_dir):
os.makedirs(self.new_dir)
self.saved_dir = self.new_dir
def get_saved_dir(self):
return self.saved_dir
Pay attention: don't use directly the previous code because in main.py I have adjusted the value of new_dir according to my environment (see /home/frank/Selenium/Insights/timestamp/ instead of your D:\Selenium\Insights\timestamp).
File conftest.py:
from main import Test
def newfunc():
test_class = Test()
test_class.test_setup()
print(test_class.get_saved_dir())
newfunc()
If you want to access to the attribute saved_dir directly without the use of method get_saved_dir() (not very object oriented) the file conftest.py becomes:
from main import Test
def newfunc():
test_class = Test()
test_class.test_setup()
# access directly to attribute saved_dir (not properly Object Oriented)
print(test_class.saved_dir)
newfunc()
Variable must be declared as belonging to the class
class Test():
def __init__(self):
self.new_dir = ""
self.saved_dir = ""
def test_setup(self):
#make new directory for downloads
self.new_dir = r"D:\Selenium\Insights\timestamp}".format(timestamp=datetime.now().strftime('%Y-%m-%d_%H-%M-%S'))
# print(self.new_dir)
if not os.path.exists(self.new_dir):
os.makedirs(self.new_dir)
self.saved_dir=self.new_dir
Then calling it
def newfunc():
dir=Test().test_setup()
print(dir.saved_dir)
I am running a websocket python file. In that,I created built-in modules in a function using imp module and I am executing a function of string using exec() in another function.
I use those built-in modules as globals parameter in exec().
But when I use those modules in the function of string, it throws following error
'module' object has no attribute 'pose'
However,using those modules outside the function of string works perfectly and returns expected values. But how to use inside the function?.
Here is the full code
import imp
import sys
import time
def generate_modules():
destination_module = imp.new_module("destination")
destination_module.destination = imp.new_module("destination")
destination_module.destination.pose = "Hello World"
# Define GUI module
gui_module = imp.new_module("GUI")
gui_module.GUI = imp.new_module("GUI")
gui_module.GUI.robotPose = lambda: "robotPose"
sys.modules["destination"] = destination_module
sys.modules["GUI"] = gui_module
return gui_module,destination_module
#Main function
def process_code():
gui_module,destination_module = generate_modules()
builtin_modules = {"GUI": gui_module,"destination":destination_module,"time": time}
globl = globals()
global_functions = globl.copy()
global_functions.update(builtin_modules)
sequential_code = """from GUI import GUI
from destination import destination
def generatepath():
data = destination.pose
pose = GUI.robotPose()
return data"""
dic = {}
exec(sequential_code,global_functions,dic)
func = dic["generatepath"]
value = func()
return value
process_code()
Thank you, any help is appreciated
As per the exec documentation:
If exec gets two separate objects as globals and locals, the code will be executed as if it were embedded in a class definition.
Notably, members of a class scope are not visible inside any nested scope. The alias resulting from from destination import destination is only visible in the top scope, not inside the function.
A simple solution is to omit the locals dictionary:
...
exec(sequential_code,global_functions)
func = global_functions["generatepath"]
...
I have many Python files (submission1.py, submission2.py, ... , submissionN.py) in the following format,
#submission1.py
def fun():
print('some fancy function')
fun()
I want to write a tester to test these submissions. (They are actually homeworks that I am grading.). I have a tester for the fun() which is able to test the function itself. However, my problem is, when I import submission.py, it runs the fun() since it calls it at the end of file.
I know that, using if __name__ == "__main__": is the correct way of handling this issue, however, our submissions does not have it since we did not teach it.
So, my question is, is there any way that I can import only fun() from the submission.py files without running the rest of the python file?
For simple scripts with just functions the following will work:
submission1.py:
def fun(x):
print(x)
fun("foo")
def fun2(x):
print(x)
fun2("bar")
print("debug print")
You can remove all bar the FunctionDef nodes then recompile:
import ast
import types
with open("submission1.py") as f:
p = ast.parse(f.read())
for node in p.body[:]:
if not isinstance(node, ast.FunctionDef):
p.body.remove(node)
module = types.ModuleType("mod")
code = compile(p, "mod.py", 'exec')
sys.modules["mod"] = module
exec(code, module.__dict__)
import mod
mod.fun("calling fun")
mod.fun2("calling fun2")
Output:
calling fun
calling fun2
The module body contains two Expr and one Print node which we remove in the loop keeping just the FunctionDef's.
[<_ast.FunctionDef object at 0x7fa33357f610>, <_ast.Expr object at 0x7fa330298a90>,
<_ast.FunctionDef object at 0x7fa330298b90>, <_ast.Expr object at 0x7fa330298cd0>,
<_ast.Print object at 0x7fa330298dd0>]
So after the loop out body only contains the functions:
[<_ast.FunctionDef object at 0x7f49a786a610>, <_ast.FunctionDef object at 0x7f49a4583b90>]
This will also catch where the functions are called with print which if the student was calling the function from an IDE where the functions have return statements is pretty likely, also to keep any imports of there are any you can keep ast.Import's and ast.ImportFrom's:
submission.py:
from math import *
import datetime
def fun(x):
print(x)
fun("foo")
def fun2(x):
return x
def get_date():
print(pi)
return datetime.datetime.now()
fun2("bar")
print("debug print")
print(fun2("hello world"))
print(get_date())
Compile then import:
for node in p.body[:]:
if not isinstance(node, (ast.FunctionDef,ast.Import, ast.ImportFrom)):
p.body.remove(node)
.....
import mod
mod.fun("calling fun")
print(mod.fun2("calling fun2"))
print(mod.get_date())
Output:
calling fun
calling fun2
3.14159265359
2015-05-09 12:29:02.472329
Lastly if you have some variables declared that you need to use you can keep them using ast.Assign:
submission.py:
from math import *
import datetime
AREA = 25
WIDTH = 35
def fun(x):
print(x)
fun("foo")
def fun2(x):
return x
def get_date():
print(pi)
return datetime.datetime.now()
fun2("bar")
print("debug print")
print(fun2("hello world"))
print(get_date()
Add ast.Assign:
for node in p.body[:]:
if not isinstance(node, (ast.FunctionDef,
ast.Import, ast.ImportFrom,ast.Assign)):
p.body.remove(node)
....
Output:
calling fun
calling fun2
3.14159265359
2015-05-09 12:34:18.015799
25
35
So it really all depends on how your modules are structured and what they should contain as to what you remove. If there are literally only functions then the first example will do what you want. If there are other parts that need to be kept it is just a matter of adding them to the isinstance check.
The listing of all the abstract grammar definitions is in the cpython source under Parser/Python.asdl.
You could use sys.settrace() to catch function definitions.
Whenever your fun() is defined, you save it somewhere, and you place a stub into the module you are importing, so that it won't get executed.
Assuming that fun() gets defined only once, this code should do the trick:
import sys
fun = None
def stub(*args, **kwargs):
pass
def wait_for_fun(frame, event, arg):
global fun
if frame.f_code.co_filename == '/path/to/module.py':
if 'fun' in frame.f_globals:
# The function has just been defined. Save it.
fun = frame.f_globals['fun']
# And replace it with our stub.
frame.f_globals['fun'] = stub
# Stop tracing the module execution.
return None
return wait_for_fun
sys.settrace(wait_for_fun)
import my_module
# Now fun() is available and we can test it.
fun(1, 2, 3)
# We can also put it again inside the module.
# This is important if other functions in the module need it.
my_module.fun = fun
This code can be improved in many ways, but it does its job.
maybe if you just want to import the fun () function from submission.py try
from submission import fun
To perform the function of fun, you must include the fun module
submission.fun()
or if you want to make it easier when calling the fun () function, give it a try
from submission import fun as FUN
FUN ()
I have two python scripts in different locations. I try to import the functions of the second one in such a way that they are integrated with the globals of the first one. That works fine. However when I call functions in the first script from the second one they cant be found.
foo.py
def run():
glob = {}
loc = {}
execfile("/path/to/bar.py", glob, loc)
currmodule = globals()
currmodule["func_in_bar"] = glob["func_in_bar"]
func_in_bar()
def func_in_foo_A():
print("fooA")
def func_in_foo_B():
print("fooB")
if __name__ == "__main__":
run()
bar.py
def func_in_bar():
func_in_foo_A()
func_in_foo_B()
When foo is run it fails with: NameError: global name 'func_in_foo_A' is not defined
In bar.py you need to add an import foo and then reference foo.func_in_foo(), etc.
Alternatively, use the form: from foo import func_in_foo
I had one script with custom exception classes in the form of:
class DirectionError(Exception):
pass
I had my functions in the same script in the form of:
def func1(x):
if x == 1:
raise DirectionError
I put my function calls into a try/except/except block in the form of:
try:
func1(2)
except DirectionError:
logging.debug("Custom error message")
sys.exit()
except:
logging.debug(traceback.format_exc())
I subsequently moved the functions into a seperate mytools.py file. I import the mytools.py file into my main python script.
I moved the custom exception classes into the mytools.py file but exception is not reaching the main python script.
How do I get those functions in the mytools.py file to send the exception back to the try/except block in my main python script?
Thanks.
It depends on how did you import mytools.
If you imported it as
import mytools
then changing:
except DirectionError:
to:
except mytools.DirectionError:
should work.
If you imported only your function with:
from mytools import func1
change it to:
from mytools import func1, DirectionError
Basically, you need to import the DirectionError class into your main code and reference it correctly.
Besides, your exception raise only when you call func1(1), and you are calling func1(2).
Define the exception in its own scriptfile and then import that file into both mytools.py and your main script