Python Using methods from other modules - python

I have two modules called Dfs and Graph.
In my Graph module, I have a class Graph and a method called ReadGraph.
In my Dfs module, I have a method that calls on ReadGraph but I get the following error message when I type: Dfs.ProcessGraph(testcase.txt,verbose=True)
Error message:
NameError: name 'testcase' is not defined
Could someone explain how to fix this?
Thanks.
From my Dfs.py module:
import sys
from Graph import *
class Dfs( object ):
def ProcessGraph(file_name, verbose):
g=ReadGraph(file_name)
From my Graph.py module:
class Graph( object ):
def ReadGraph( file_name ):

Remove your class declaration from Graph.py. When you import all from a file you get all top level objects. In this case it's the Graph class itself, not its methods.
Also you need to pass string 'testcase.txt' not testcase.txt.

You have multiple problems here:
If you from Graph import * (which is bad practice to start with), you bring Graph into your name space. However, ReadGraph is inside Graph, so to access it you need Graph.ReadGraph.
Having done that, you try to call Dfs.ProcessGraph(testcase.txt,verbose=True). The first argument is interpreted as "pass the txt attribute of the object referenced by name testcase, which doesn't exist. Instead, you mean "testcase.txt" (quoted to make it a string).
Having done all of that, you get e.g. TypeError: unbound method ProcessGraph() must be called with Dfs instance as first argument (got str instance instead). When you call an instance method, the first argument, self by convention, is the instance itself. You have two choices; either a) make e.g. ProcessGraph a #staticmethod, and access it Graph.ReadGraph; or b) move it outside the class, then you can access it directly like you tried to in the first place. As you don't seem to have any class or instance attributes, it's not clear why you are bothering with the classes at all.
What it should probably look like:
import sys
from Graph import read_graph
def process_graph(file_name, verbose):
g = read_graph(file_name)
Graph.py module (note absence of class Graph):
def read_graph(file_name):
...
(Generally, I suggest you read PEP 8).

your code should be : Dfs.ProcessGraph('testcase.txt',verbose=True)
and not Dfs.ProcessGraph(testcase.txt,verbose=True)
'testcase.txt' # is a string and should be between quotes
also check if it is in the same directory where your code live else point to it
plus in DFs you should instantiate Graph :
from Graph.Graph import *
g = Graph()
grf = g.ReadGraph('filename')
EDIT: to be more precise
in Graph module:
class Graph(object):
def __init__(self):
pass # for the example now
def read_graph(self, file_name):
return file_name
in Dfs Module:
from Graph import *
class Dfs(object):
def __init__(self):
pass # for the example now
def ProcessGraph(file_name, verbose):
g = Graph()
file_name = Graph.read_graph(file_name)

Related

Getting functions from Python file as passable objects

I have a Python file from which I would like to get all functions. I want to pass these functions to another file in order to collect data about these functions.
For Example.py:
class Example:
def method_to_extract(name: str) -> none:
print(name)
I want to extract this method as an object through the file name and pass it as an argument to another function, like
func = magic_method(Example.py) # returns method_to_extract as a callable object
collect_data(func)
Is this possible? So far, I have only been able to extract the names of functions as strings. However, that does not help me, as I want to collect data about the functions like the number of arguments, type hints, and more, and therefore need to be able to access the entire function.
I also tried getting the function using func = getattr(class, funcname), but I wasn't able to pass func as a parameter and extract the data I need.
I can think of 3 solutions, dependant on your particular needs.
Simplest one: don't use classes, just global functions:
# file1.py
def method_to_extract(name):
print(name)
And then in another file just import and use it:
# file2.py
from file2 import method_to_extract
method_to_extract()
In case you especially want to use methods inside of a class, you can make them static with #staticmethod decorator:
# file1.py
class Example:
#staticmethod
def method_to_extract(name):
print(name)
And then in another file just import and use it:
# file2.py
from file2 import Example
Example.method_to_extract()
More on staticmetod decorator here: https://www.programiz.com/python-programming/methods/built-in/staticmethod
Of course, not all of your methods can be static. Then you just have to create an instance of the class and then use its methods:
# file1.py
class Example:
def method_to_extract(name):
print(name)
And then in another file just import and use it:
# file2.py
from file2 import Example
instance = Example()
instance.method_to_extract()
Basically, the above three approaches are in general only possible ways of accessing some particular function or method in python and the fact of exporting them to another file doesn't change a thing.
Something like this:
from Example import Example.method_to_extract as mte
collect_data(mte)
The code you show is not entirely correct; you would have to make method_to_extract a #staticmethod if it's inside the Example class. Perhaps a better solution then would be to define it outside the class; or define a #classmethod which you can call to return a method of that class as an object. But both of these are generally best avoided; your class should probably simply have a method which implements collect_data, and your code should simply call that instead.

Returning class object from Oct2Py

I'm trying to run a basic MATLAB script that defines a class, and get that class object returned to python. I don't know MATLAB well, and am very new to Oct2Py so I may be completely misunderstanding how to do this. Any help would be greatly appreciated.
Here is the Matlab file (taken from here)
classdef BasicClass
properties
Value {mustBeNumeric}
end
methods
function r = roundOff(obj)
r = round([obj.Value],2);
end
function r = multiplyBy(obj,n)
r = [obj.Value] * n;
end
end
end
And I call this in the python script with the following
from oct2py import octave
octave.addpath(r'C:\Users\i13500020\.spyder-py3\IST')
oclass = octave.class_example(nout=1)
when I run this I get a warning that prints four times and then an error message
First:
warning: struct: converting a classdef object into a struct overrides the access restrictions defined for properties. All properties are returned, including private and protected ones.
And then:
TypeError: 'NoneType' object is not iterable
I don't have any trouble running the roundtrip example from the Oct2Py page, so I know my installation is fine
I've written a small work around to use custom matlab classes with oct2py.
Currently, this approach supports only access to member functions (and not attributes) of the Matlab class as this was what I needed:
from oct2py import octave
class MatlabClass():
_counter = 0
def __init__(self, objdef) -> None:
"""Use matlab object as python class.
Args:
objdef (str): Class initialization as string.
"""
MatlabClass._counter += 1
self.name = f"object_for_python{MatlabClass._counter}"
octave.eval(f"{self.name} = {objdef};")
def __getattr__(self, item):
"""Maps values to attributes.
Only called if there *isn't* an attribute with this name
"""
def f(*args):
call = f"{self.name}.{item}({','.join([str(arg) for arg in args])});"
return octave.eval(call)
return f
use this class as followed:
param = 0.24 # random value you might need for class initialization
oclass = MatlabClass(f"BasicClass({param})")
x = oclass.roundOff()
y = oclass.multiplyBy(2)
Note: you might need an init function in your octave code to run set your Value variable.

Dynamically changing the definition of a module and class without changing the module code directly

I am not even sure, whether the following is possible.
My question is easily described with the following code.
My module is defined as
asdf = 5
class MyClass:
def myfct(self):
return asdf
I have a module which defines a complex class.
It uses a definition of the module it is in.
Here I call it asdf.
In fact, asdf is a class definition in itself, I just have it as an integer here for simplicity sake.
I want to remove asdf from the module as a member, but still have the class work.
So before deleting it from the module, I first write it into the definition MyClass dynamically after loading the module, then I delete it from the module.
import mymodule
MyClass.asdf = asdf
del sys.modules['mymodule'].asdf
Finally I use this to instantiate the new class
myobj = mymodule.MyClass()
myobj.myfct()
but of course, this throws the error
NameError: name 'asdf' is not defined
How can I make the class work without changing the code of the class, namely without changing return asdf to return self.asdf and but still deleting asdf from the module (and not adding other module attributes). However, I am allowed to change the function dynamically after import mymodule.
Keep in mind that the function definition is very complex, so something like writing it again with exec (https://stackoverflow.com/a/11291851/4533188) is not an option.
One idea of mine is to change the signature of the method dynamically such that it receives an optional argument asdf. That way, the code inside would use that variable, but I do not know how to do that. Possibly helpfull might be Byteplay/Metaclasses:
http://www.voidspace.org.uk/python/weblog/arch_d7_2006_12_16.shtml#e583
https://wiki.python.org/moin/ByteplayDoc
http://www.voidspace.org.uk/python/articles/metaclasses.shtml
http://www.vrplumber.com/programming/metaclasses-pycon.pdf
The following answer works, but is semi-great.
Basically we save the original method in a dummy variable myfct_original.
Then we redefine our function such that the variable MyClass.asdf is copied to the module, the original method is applied, and the variables is removed from the module - so for a short time it is available in the module.
asdf = 5
class MyClass:
def myfct(self, test=1):
return asdf
MyClass.asdf = asdf
MyClass.myfct_original = MyClass.myfct
del sys.modules[__name__].asdf
delattr(MyClass, 'myfct')
def newmyfct(self, *args, **kwargs):
setattr(sys.modules[__name__], 'asdf', MyClass.asdf)
result = MyClass.myfct_original(self, *args, **kwargs)
del sys.modules[__name__].asdf
return result
setattr(MyClass, 'myfct', newmyfct)
myobj = MyClass()
myobj.myfct()
Maybe someone can do better (see end of the question).

__subclasses__ not showing anything

I'm implementing a function that returns an object from the appropriate subclass. If I move SubClass from base.py, no subclasses appear for __subclasses__. Are they required to be in the same file?
Perhaps the fact that I'm never importing directly subclass.py hides the subclass from python? What can I do? I have even checked the attribute __mro__ and get_subclass points to the right class.
# project/main.py
from project.src.base import get_subclass
obj = get_subclass(cls,name) # Returns an object of a subclass of cls
# project/src/subclass.py
from project.src.base import BaseClass
class SubClass(BaseClass):
pass
# project/src/base.py
def get_subclass(cls,name):
subclss = cls.__subclasses__ # This is returning an empty list
pass
class BaseClass(object):
pass
Python only runs code of modules that are imported. If you move code to a different module but never import it, Python does not know about its contents.
You have to import the files containing the subclasses you want accessible.
# project/src/__init__.py
import project.src.base # executes the ``BaseClass`` definition
import project.src.subclass # executes the ``SubClass`` definition
Note that it does not really matter where you import these - they must be imported before you need SubClass to appear in __subclasses__, though.

Python class static methods

I want to create a kind of utility class which contains only static methods which are callable by the name class prefix. Looks like I'm doing something wrong :)
Here is my small class:
class FileUtility():
#staticmethod
def GetFileSize(self, fullName):
fileSize = os.path.getsize(fullName)
return fileSize
#staticmethod
def GetFilePath(self, fullName):
filePath = os.path.abspath(fullName)
return filePath
Now my "main" method:
from FileUtility import *
def main():
path = 'C:\config_file_list.txt'
dir = FileUtility.GetFilePath(path)
print dir
and I got an error: unbound method GetFilePath() must be called with FileUtility instance as first argument (got str instance instead).
A have a few questions here:
What am I doing wrong? Should not the static method be callable by classname?
Do I really need a utility class, or are there other ways to achieve the same in Python?
If I try to change the code in main I'm getting: TypeError: GetFilePath() takes exactly 1 argument (2 given)
The new main:
from FileUtility import *
def main():
objFile = FileUtility()
path = 'H:\config_file_list.txt'
dir = objFile.GetFilePath(path)
print dir
You're getting the error because you're taking a self argument in each of those functions. They're static, you don't need it.
However, the 'pythonic' way of doing this is not to have a class full of static methods, but to just make them free functions in a module.
#fileutility.py:
def get_file_size(fullName):
fileSize = os.path.getsize(fullName)
return fileSize
def get_file_path(fullName):
filePath = os.path.abspath(fullName)
return filePath
Now, in your other python files (assuming fileutility.py is in the same directory or on the PYTHONPATH)
import fileutility
fileutility.get_file_size("myfile.txt")
fileutility.get_file_path("that.txt")
It doesn't mention static methods specifically, but if you're coming from a different language, PEP 8, the python style guide is a good read and introduction to how python programmers think.
You really shouldn't be creating static methods in Python. What you should be doing is putting them at the global function level, and then accessing the module they're in when you call them.
foo.py:
def bar():
return 42
baz.py:
import foo
print foo.bar()
Static methods don't get the object passed in as the first parameter (no object)
remove the self parameter and the calls should work.
The import problem is relevant too.
And the static comment relevant too.
In python, java-like (or whatever) static methods are not widely used as they don't really have a purpose.
Instead, you should simply define your "methods" as functions in a module:
#module1.py
def fun1():
return do_stuff()
def fun2(arg):
return do_stuff_with_arg(arg)
#main.py
import module1
if __name__ == '__main__':
a = module1.fun()
print module1.fun2(a)
Just remove self in methods definition. Your intention is to use as static. Self is to work with instance of that class.
Just remove the self in the function definition. Since your using the static functions so you need not pass self as an argument for the functions.
So your class and function should be like this:
class FileUtility():
#staticmethod
def GetFileSize(fullName):
fileSize = os.path.getsize(fullName)
return fileSize
#staticmethod
def GetFilePath(fullName):
filePath = os.path.abspath(fullName)
return filePath
If you want to use your functions defined in the class, you have just to create an instance of your class and apply the function.
So the result is :
dir = FileUtility().GetFilePath(path)
Just add () after your class name.
#staticmethod is not needed as you are using standard function, not static. But in your case the result is the same.

Categories