Using Functions from Other .py Files - python

So I'm very new to Python and programming in general. I've run into an issue with my text game. I'm trying to create a function (pretty sure 'def (name) is a function, right?)in a .py called 'locationMenu' and use it in my main game file. Here is the start of my locationMenu.py (the rest is simply prints and if/elif/else statements.
from main import Engine, Hallway, Canteen, Bedroom, Room
class locationsMenu():
def locationMenu(self):
and here is the place in my main game file where I am trying to use the 'locationMenu' function that I just created.
locationMenu()
That is just one line after I made a choice with input, etc. but now I would like to skip to the locationMenu that is in the other file.
Any help much appreciated. Please don't use "big words" because as I said I'm still very new to programming in general.

locationMenu() is an instance method of the locationsMenu() class, so you'd need to create an instance and call the method on it, something like:
from locationMenu import locationsMenu
my_menu = locationsMenu() # Create a new object
my_menu.locationMenu() # Call its instance method
If you were to just try locationsMenu.locationMenu() then you'd get something like this error:
Traceback (most recent call last):
File "./prog.py", line 3, in <module>
locationsMenu.locationMenu()
TypeError: locationMenu() missing 1 required positional argument: 'self'
because locationMenu() is not a class method, and you're trying to call it in the absence of a locationsMenu object.
If you don't want it inside a class at all, then make it a regular function, and do:
locationMenu.py:
from main import Engine, Hallway, Canteen, Bedroom, Room
def locationMenu():
print("In function locationMenu()")
prog.py:
from locationMenu import locationMenu
locationMenu()

Related

Python import interaction

Well. I have a main file with a class in it. I have another file, where i wanna store functions (for the sake of simplicity), which use functions of that class. And I wanna import the second file into the first one, so i can use those functions in main file. And that's where I encountered a problem.
If I'm just importing the second file into the first one, I have an error which says that in second file the class is not defined.
If I'm importing the first file into the second one AND the second one into the first one, I have an error in main file, which says that function I defined in second one doesn't exist.
That's the simpliest variant I can get. File 1:
import random
import Test2
class randoms():
def __init__(self):
pass
def random_shit():
a=random.randrange(19)
return a
WTF= randoms()
Test2.printer()
File 2:
import Test
def printer():
print(Test.WTF.random_shit())
First off some python customs: usually classes are defined with capital letters:
class Randoms():
pass
The problem is in file 2 and the fix will fix both errors for both files you define the object WTF in file 1 and then use it in a function. Basically you are using a variable which doesn’t exist inside the function. What you should do is initialize the object WTF inside the function you would like to use:
def printer():
WTF = Test.randoms()
print(WTF.random_shit())
You can remove the initialization inside the file 1.
Hope this helps.

How to use *args in a python class?

I am trying to get some args working in a class, I already got it running in a function from How to use *args in a function?.
I'm trying to get that function into a class but I don't seem to understand how to initialize that class which has an init function taking *args. The code is as following :
class classname(object):
def __init__(self, *args):
<code-snip>
...
</code-snip>
if __name__ == "__main__":
start = classname()
start()
So here I'm confused on what to do with 'start()'. Do I have to use 'start(*sys.argv[1:])' or 'start()'. Both doesn't seem to work. I want to get the *args which is expected in init to be passed properly.
Any pointers please.
Thanks a ton..
======
I'm sorry if I wasn't clear on detailing how it didn't work.
a) While using start(*sys.argv[1:])
Traceback (most recent call last):
File "check.py", line 126, in <module>
start(*sys.argv[1:])
TypeError: 'check' object is not callable
b) While using start(), I get :
Traceback (most recent call last):
File "check.py", line 126, in <module>
start()
TypeError: 'check' object is not callable
These were the errors which came up.
#alko, yes you are correct. I was looking on how to get the *args in init passed properly.
Objects are instantiated by passing arguments to class constructor. They are in turn initalized with __init__ function. In your example this would be
start = ClassName(*sys.argv[1:])
that expression is processed as follows:
New instance of classname is instantiated with object.__new__(ClassName, *sys.argv[1:]) named start in local namespace. From now on start object may be referenced inside your if __name__ == "__main__" script.
Its contents are in turn initialized invoking start.__init__(*sys.argv[1:]). Note that args to __init__ are the same passed to constructor.
And read PEP 8 for python naming convention. That is:
Class names should normally use the CapWords convention.
Your example contains a class which is first instantiated - which involves calling __init__() - and then called - which is done by calling __call__().
So your stuff should be put in the call start = classname(...) in order to be passed to __init__().
The call to the newly instantiated object will fail, however, unless it contains a __call__() method. That would have been easier to answer if you had told us what
Both doesn't seem to work.
exactly means.

Accessing a method using getattr

When creating a new class instance, I'm trying to call a method in a different class however can't get it to work. Here's what I have:
class DataProject(object):
def __init__(self, name=none,input_file=None,datamode=None,comments=None,readnow=True):
..............
# here's where I'm trying to call the method in the other class
if type(input_file) == str:
self.input_file_format = self.input_file.split(".")[-1]
if readnow:
getattr(Analysis(),'read_'+self.input_file_format)(self,input_file)
class Analysis(object):
def __init__(self):
pass # nothing happens here atm
def read_xlsx(self,parent,input_file):
"""Method to parse xlsx files and dump them into a DataFrame"""
xl = pd.ExcelFile(input_file)
for s in sheet_names:
parent.data[s]=xl.parse(s)
I'm getting a NameError: global name 'read_xlsx' is not defined when I run this with afile.xlxs as input which made me think that I just discovered a massive hole in my Python knowledge (not that there aren't many but they tend to be hard to see, sort of like big forests...).
I would have thought that getattr(Analysis(), ... ) would access the global name space in which it would find the Analysis class and its methods. And in fact print(globals().keys()) shows that Analysis is part of this:
['plt', 'mlab', '__builtins__', '__file__', 'pylab', 'DataProject', 'matplotlib', '__package__', 'W32', 'Helpers', 'time', 'pd', 'pyplot', 'np', '__name__', 'dt', 'Analysis', '__doc__']
What am I missing here?
EDIT:
The full traceback is:
Traceback (most recent call last):
File "C:\MPython\dataAnalysis\dataAnalysis.py", line 101, in <module>
a=DataProject(input_file='C:\\MPython\\dataAnalysis\\EnergyAnalysis\\afile.xlxs',readnow=True)
File "C:\MPython\dataAnalysis\dataAnalysis.py", line 73, in __init__
getattr(Analysis(),'read_'+self.input_file_format)(self,input_file)
File "C:\MPython\dataAnalysis\dataAnalysis.py", line 90, in read_xls
read_xlsx(input_file)
NameError: global name 'read_xlsx' is not defined
My main call is:
if __name__=="__main__":
a=DataProject(input_file='C:\\MPython\\dataAnalysis\\EnergyAnalysis\\afile.xlx',readnow=True)
From the full traceback, it appears that your DataProject class is calling (successfully) the Analysys.read_xls method, which in turn is trying to call read_xlsx. However, it's calling it as a global function, not as a method.
Probably you just need to replace the code on line 90, turning read_xlsx(input_file) into self.read_xlsx(input_file), though you might need to pass an extra parameter for the parent DataProject instance too.
getattr() works as you describe it in both Python2.x and Python3.x. The bug must be somewhere else.
This modification of your code (none of the core logic is changed) works fine for instance:
class DataProject(object):
def __init__(self, name="myname",input_file="xlsx",datamode=None,comments=None,readnow=True):
if type(input_file) == str:
self.input_file_format = input_file.split(".")[-1]
if readnow:
getattr(Analysis(),'read_'+self.input_file_format)(self,input_file)
class Analysis(object):
def __init__(self):
pass # nothing happens here atm
def read_xlsx(self,parent,input_file):
"""Method to parse xlsx files and dumpt them into a DataFrame"""
print("hello")
a=DataProject()
Output is:
$ python3 testfn.py
hello
Why using getattr() in this way is usually a bad idea
The way you are using getattr forces a naming convention on your methods (read_someformat). The naming of your methods should not be a core part of your program's logic. - You should always be able to change a function's name at every call and definition of that function and leave behaviour of the program intact.
If a file format needs to be handled by a specific method this logic should be delegated to some unit (e.g a function) with responsibility for this. One way (there are others) of doing this is to have a function which takes the input and decides which function needs to handle it:
def read_file(self,file,format):
if format == `xls`:
self.read_xls(file)
if format == `csv`:
self.read_csv(file)
The above snippet does have its issues too (a better way to do it would be the chain of responsibility pattern for example) but it will be fine for small scripts and is much nicer.

How to run "exec" from the global scope in python

I have a Class. In that class I have a function.
In the function, I have a string variable that holds definitions of several python functions.
I would like from the function to create the functions that are defined in the variable, such that they will be created in the global scope.
After this operation, I would like to be able to call to the new function from the global scope.
For example:
class MyClass:
def create_functions():
functions_to_create = """
def glob1():
return "G1"
def glob2():
return "G2"
"""
# ----> HERE IS THE MISSING PART, LIKE RUNNING exec in the global scope <----
# The following function should work:
def other_function_in_global_scope():
print "glob1: %s, glob2: %s" % (glob1(), glob2())
What should be in the MISSING PART?
Thanks in advance!!!
In python the overrides can monkey-patch anything anytime, but if you just evaluate a bit of code in global namespace, the risk of inadvertent symbol conflict. I'd suggest instead the customer would provide a module and your code would call functions in it if they were defined there (and default implementations otherwise).
That said, documentation suggests:
exec(functions_to_create, globals())
Several things first. What is your reason to creating a function to create other functions? What are you trying to do? There might be a better way. Also here is another way to so called create function that doesn't involve playing around with exec.
>>> def create_functions():
... global glob1
... def glob1():
... return "G1"
...
>>> glob1()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'glob1' is not defined
>>> create_functions()
>>> glob1()
'G1'
>>>
Edit
Injecting source code without exec (THIS IS NOT A GOOD IDEA AT ALL)
Have you customer submit their code then just do a custom import
Customer Submit Code
Save that code as say custom.py
In your code that you want to let the customer inject into do something like the following
import os
if os.path.exists("custom.py"):
import custom
custom.inject()
That way they can give you their code you call inject and they can change things.

Attribute Error when trying to setlabel in wx python

This seems like a simple issue but I'm having a very difficult time understanding why I am getting the following error:
Traceback (most recent call last):
File "....py", line 46, in update
self.Grob3Text.SetLabel('Grob 3: ' + str(Grob3))
AttributeError: 'Frame' object has no attribute 'Grob3Text'
When running the following script:
Please see -
.
I understand the message is telling me that the static text variable 'Grob3Text' is not defined in the Frame, but it appears to me that the definition for update event is under the same class. All I'm trying to do is execute the faultreport function and update the static text. I have got this working in another script but for whatever reason I am overlooking something here.
You create a local variable Grob3Text in __init__, but you don't actually store it as an instance attribute on the class instance. To do that, you could simply do:
self.Grob3Text = Grob3Text
in __init__ after you create Grob3Text.

Categories

Resources