getting two classes to interact - python

I am having trouble getting two classes to interact. Here is the code for the first class where i am importing file youtest.py:
from youtest import MyTest
class RunIt(object):
def __init__(self):
self.__class__ = MyTest
r = RunIt()
r.iffit()
I am trying to run class MyTest through this class (code below):
from sys import exit
class MyTest(object):
def death(self):
exit
def iffit(self):
oh_no = raw_input(">")
print "What is your name?"
if oh_no == "john":
print "welcome john"
else:
print "game over"
return 'death'
when i run this i get the following:
File "youtest.py", line 19
return 'death'
SyntaxError: 'return' outside function
Hope this question is clear enough thanks for the help.

The lines starting from print "What is your name?" are not indented properly. In python the whitespace is significant.

In Python, this isn't how to subclass.
from youtest import MyTest
class RunIt(MyTest): pass
r = RunIt()
r.iffit()
Although in this example r = MyTest() would work fine.
Your SyntaxError is triggered by your misuse of white space. Use four spaces for each indentation level, as is standard in Python, so you can clearly see the organization of things.
You have another problem: return 'death' will not call death, you need to return death() if that's what you want.
Finally, death() will not do anything with exit, just reference it. You need to do exit().

Related

python modules, call main class in modules

this is my main module, I can call other module's function with it:
#main.py
from module_1 import module_1
class APP:
def option(self):
print("[1]:.....\n[2]:.......")
option = int(input(":"))
if (option == 1):
module_1().do_something_1() #I called module_1
APP().option()
Let's say the user chose the first option, the program will call the function in the module_1
#module_1.py
class module_1:
def do_something_1(self):
#.........................
again = input("Do you wanna start again?")
if (again == "Y"):
#what I'm trying to do is here, I want to return the option function again in main.py
else:
#................
And user wanted to restart program and Asked question with Y, How can the program return the main.py(APP().option())?
[UPTADE_1]
I actually thought a circular import would work for me here but got an error
main.py:
#main.py
from module_1 import module_1
class APP:
def option(self):
print("[1]:.....\n[2]:.......")
option = int(input(":"))
if (option == 1):
module_1().do_something_1() #I called module_1
APP().option()
module_1.py:
from main import APP
class module_1:
def do_something_1(self):
print(".........")
again = input("Do you wanna start again?")
if again=="Y":
return APP().option()
else:
#.......
I get this error:
.............................
from main import APP
ImportError: cannot import name 'APP' from partially initialized module 'main' (most likely due to a circular import)
.............................
[UPTADE_2](after Grismar's answer)
main.py:
from File import*
class Options:
def __init__(self):
#...................
def ask(self):
try:
option=int(input("==>"))
except Exception as error:
#......................................
return Options().ask()
if option==1:
File().delete_all_files_extension()
elif option==2:
#.........
elif option==3:
#.........
elif option==4:
#..........
elif option==5:
#.........
elif option==6:
sys.exit()
Options().ask()
Let's say the user chose the first option, the program will call the function in the File
import sys
import os
class File:
def __init__(self):
self.deleted_files_number = 0
self.deleted_files_extension_number = 0
def delete_all_files(self):
try:
path = input("[+]Path:")
except Exception as error:
print("ERROR:%s"%error)
#.....................
#I want to return the option function again in main.py
try:
file = open("log[delete_all_files].txt","w")
if (os.path.exists(path)==True):
for r,d,f in os.walk(path):
for file in f:
time.sleep(0.001)
print("[*]%s" %os.path.join(r,file))
os.remove(os.path.join(r,file))
open("log[delete_all_files].txt","a+").write(str(os.path.join(r,file)+"\n"))
self.deleted_files_number +=1
print("[*]Deleted %s file" %self.deleted_files_number)
again=input("[+]Do you wanna start again?[Y/N]").upper()
if (again=="Y"):
#here it is, the program has to go back to main.py so it can show what can be selected again.
else:
exit()
I mean, the program will return if an error or something different occurs within the module, not after the module has finished its work.
In your example, in main.py, you call APP.option(). APP.option() calls module_1().do_something_1(), where module_1 is a class imported from module_1.
You want module_1().do_something_1 to then call APP.option() again (under certain conditions).
A few remarks:
you would do well to follow Python naming conventions and name APP App.
there appears to be little or no utility in wrapping the module module_1's functionality in a class called module_1; all this gets you is two completely different entities sharing the same name. If you want to capture the functionality in a class, you should probably name it something that reminds developers using it of its function.
you're calling APP().option(), which means you're instantiating a new object every time, creating a new APP() with a new menu every time
most importantly, since APP.option() can call module_1().do_something_1 indefinitely and module_1().do_something_1 can call APP.option(), you run the risk of creating an application that ends up exhausting the recursion depth.
Object-oriented software design is all about picking the correct scope for your classes, giving them clear jobs that encapsulate behaviour and data that clearly goes together; to create software that's easier to maintain and extend.
The main function of your App class appears to be to present the user with options and execute matching functionality. The main function of module_1 appears to be to 'do something' and then return to the main loop. You want to present the user with the options again or allow them to exit the app, after 'doing something'.
From a design perspective, it seems to make more sense to have the App present the user with the 'start again' question - after all, it has nothing to do with whatever was done in module_1. If it does depend on what happens there, it makes sense to have the do_something_1() method return a result and base the decision to continue on the returned value.
You could even base that return value on the question you ask the user, although I don't like that design decision:
if again=="Y":
return True
else:
# ... do something else ...
return False
And in main.py:
def option(self):
again = True
while again:
print("[1]:.....\n[2]:.......")
option = int(input(":"))
if (option == 1):
again = module_1().do_something_1()
Another solution could be to create the module_1, passing the App it belongs to as an owner and keeping a reference to it in the object. Something like:
def __init__(self, owner):
self.owner = owner
# ...
if again=="Y":
return self.owner.option()
That solves the object creation issue, but is still circular of course.
You can have modules importing parts of each other and the correct way to do that would be by adding them to a package. However, you would still have to find a way to get around circular creation of the classes - if Class1 creates an instance of Class2, but
Class2 creates an instance of Class1, you can see where that's going.
What's wrong with something like this:
main.py
from module_1 import Class_1
class App:
def menu(self):
run_menu = True
while run_menu :
print("[1]:.....\n[2]:.......")
option = int(input(":"))
if (option == 1):
Class_1().do_something_1()
print(".........")
run_menu = input("Do you wanna start again?") == "Y"
App().menu()
module_1.py
class Class_1:
def do_something_1():
print('doing something')
return
The problem you're having is more a problem of design, not so much of the language. If you have an example of functionality where you feel the circular import is a requirement, you should probably post a question with that example specifically - but you're likely to be marked a duplicate of one of many questions asking about circular imports.
The short answer is: there's almost always a better solution.

python Cmd module autocompletion error in nested interpreters

I'm trying to create a debug console for the main console I'm writing using Cmd module.
The debug console should have all the main console attributes and ontop some more extentions used for debug and advanced users.
The best answer to fir my needs was the second answer of the following post:
object inheritance and nested cmd
My implementation currently looks like this:
class MainConsole(cmd.Cmd):
def __init__(self):
cmd.Cmd.__init__(self)
def do_something(self, line):
print "do something!"
return
def do_something2(self, line):
print "do something2!"
return
class SubConsole1(cmd.Cmd):
def __init__(self, maincon):
cmd.Cmd.__init__(self)
self.maincon = maincon
self.register_main_console_methods()
def register_main_console_methods(self):
main_names = self.maincon.get_names()
for name in main_names:
if (name[:3] == 'do_') or (name[:5] == 'help_') or (name[:9] == 'complete_'):
self.__dict__[name] = getattr(self.maincon, name)
Observation:
When I hit "help", I indeed see all the upper console methods and I'm able to invoke them.
Problem:
The autocompletion of the actual commands is not available.
The expected behaviour of the shell when hitting "some" and tab would be to autocomplete it to "something". This doesn't happen.
When I tried to debug the issue, I found out that self.get_names() method which is used by the self.completenames() function returns the list of methods before the registration.
So what's actually happening is that the newly added methods are "removed" from the nested console, although I can invoke them.
I'd love some insights on that.
Thanks!
You can solve your problem by extending get_names method
import cmd
class MainConsole(cmd.Cmd):
def __init__(self,console_id):
cmd.Cmd.__init__(self)
self.console_id = console_id
def do_something(self, line):
print "do something!",self.console_id
return
def do_something2(self, line):
print "do something2!",self.console_id
return
class SubConsole1(cmd.Cmd):
def __init__(self, maincon):
cmd.Cmd.__init__(self)
self.maincon = maincon
self.register_main_console_methods()
def do_super_commands(self,line):
print "do supercommand",self.maincon
def register_main_console_methods(self):
main_names = dir(self.maincon)
for name in main_names:
for prefix in 'do_','help_','complete_', :
if name.startswith(prefix) and name not in dir(self):
self.__dict__[name] = getattr(self.maincon, name)
def get_names(self):
result = cmd.Cmd.get_names(self)
result+=self.maincon.get_names()
return result
SubConsole1(MainConsole("mainconsole")).cmdloop()
it is not guaranteed to work on subsequence version of python as it is undocumented behavior of python 2.7
EDIT: replacing the subclassing method by mainconsole as a member as required in comment
EDIT 2: don't replace the existing methods in SubConsole to keep method as do_help

Is it possible to create a dynamic localized scope in Python?

I have a scenario where I'm dynamically running functions at run-time and need to keep track of a "localized" scope. In the example below, "startScope" and "endScope" would actually be creating levels of "nesting" (in reality, the stuff contained in this localized scope isn't print statements...it's function calls that send data elsewhere and the nesting is tracked there. startScope / endScope just set control flags that are used to start / end the current nesting depth).
This all works fine for tracking the nested data, however, exceptions are another matter. Ideally, an exception would result in "falling out" of the current localized scope and not end the entire function (myFunction in the example below).
def startScope():
#Increment our control object's (not included in this example) nesting depth
control.incrementNestingDepth()
def endScope():
#Decrement our control object's (not included in this example) nesting depth
control.decrementNestingDepth()
def myFunction():
print "A"
print "B"
startScope()
print "C"
raise Exception
print "D"
print "This print statement and the previous one won't get printed"
endScope()
print "E"
def main():
try:
myFunction()
except:
print "Error!"
Running this would (theoretically) output the following:
>>> main()
A
B
C
Error!
E
>>>
I'm quite certain this isn't possible as I've written it above - I just wanted to paint a picture of the sort of end-result I'm trying to achieve.
Is something like this possible in Python?
Edit: A more relevant (albeit lengthy) example of how this is actually being used:
class Log(object):
"""
Log class
"""
def __init__(self):
#DataModel is defined elsewhere and contains a bunch of data structures / handles nested data / etc...
self.model = DataModel()
def Warning(self, text):
self.model.put("warning", text)
def ToDo(self, text):
self.model.put("todo", text)
def Info(self, text):
self.model.put("info", text)
def StartAdvanced(self):
self.model.put("startadvanced")
def EndAdvanced(self):
self.model.put("endadvanced")
def AddDataPoint(self, data):
self.model.put("data", data)
def StartTest(self):
self.model.put("starttest")
def EndTest(self):
self.model.put("endtest")
def Error(self, text):
self.model.put("error", text)
#myScript.py
from Logger import Log
def test_alpha():
"""
Crazy contrived example
In this example, there are 2 levels of nesting...everything up to StartAdvanced(),
and after EndAdvanced() is included in the top level...everything between the two is
contained in a separate level.
"""
Log.Warning("Better be careful here!")
Log.AddDataPoint(fancyMath()[0])
data = getSerialData()
if data:
Log.Info("Got data, let's continue with an advanced test...")
Log.StartAdvanced()
#NOTE: If something breaks in one of the following methods, then GOTO (***)
operateOnData(data)
doSomethingCrazy(data)
Log.ToDo("Fill in some more stuff here later...")
Log.AddDataPoint(data)
Log.EndAdvanced()
#(***) Ideally, we would resume here if an exception is raised in the above localized scope
Log.Info("All done! Log some data and wrap everything up!")
Log.AddDataPoint({"data": "blah"})
#Done
#framework.py
import inspect
from Logger import Log
class Framework(object):
def __init__(self):
print "Framework init!"
self.tests = []
def loadTests(self, file):
"""
Simplifying this for the sake of clarity
"""
for test in file:
self.tests.append(test)
def runTests(self):
"""
Simplifying this for the sake of clarity
"""
#test_alpha() as well as any other user tests will be run here
for test in self.tests:
Log.StartTest()
try:
test()
except Exception,e :
Log.Error(str(e))
Log.EndTest()
#End
You can achieve a similar effect with a context manager using a with statement. Here I use the contextlib.contextmanager decorator:
#contextlib.contextmanager
def swallower():
try:
yield
except ZeroDivisionError:
print("We stopped zero division error")
def foo():
print("This error will be trapped")
with swallower():
print("Here comes error")
1/0
print("This will never be reached")
print("Merrily on our way")
with swallower():
print("This error will propagate")
nonexistentName
print("This won't be reached")
>>> foo()
This error will be trapped
Here comes error
We stopped zero division error
Merrily on our way
This error will propagate
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
foo()
File "<pyshell#3>", line 10, in foo
nonexistentName
NameError: global name 'nonexistentName' is not defined
It cannot be done with an ordinary function call as in your example. In your example, the function startScope returns before the rest of the body of myFunction executes, so startScope can't have any effect on it. To handle exceptions, you need some kind of explicit structure (either a with statement or a regular try/except) inside myFunction; there's no way to make a simple function call magically intercept exceptions that are raised in its caller.
You should read up on context managers as they seem to fit what you're trying to do. The __enter__ and __exit__ methods of the context manager would correspond to your startScope and endScope. Whether it will do exactly what you want depends on exactly what you want those "manager" functions to do, but you will probably have more luck doing it with a context manager than trying to do it with simple function calls.

I have a Python code that is given below, when I run this global name PDBAttributes is not defined

#!/usr/bin/env python2.7
##-*- mode:python;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t;python-indent:2 -*-'
import noesy
import argparse
import library
parser =argparse.ArgumentParser(description="read pdb file",
add_help=True)
parser.add_argument("file",help="protein pdb file")
library.add_standard_args( parser )
args = parser.parse_args()
def read_structure(pdbfile):
struct=[]
for line in pdbfile:
if len(line):
struct.append(PDBAttributes.read_from_line(line))
return struct
pdb=read_structure(open(args.file,'r'))
class PDBAttributes:
def __init__(self, atomindex=1, atom=noesy.Atom(), atomx=1, atomy=1, atomz=1):
self._atomindex=atomindex
self._atom=atom
self._atomx=atomx
self._atomy=atomy
self._atomz=atomz
def __str__(self):
s='ATOM %(_atomindex)d %(_atom)s at %(_atomx)8.3f %(_atomy)8.3f %(_atomz)8.3f'%self.__dict__
return s
def atom(self):
return self._atom
def atomindex(self):
return self._atomindex
def atomx(self):
return self._atomx
def atomy(self):
return self._atomy
def atomz(self):
return self._atomz
#classmethod
def read_from_line(obj,line):
tags=line.split()
atomindex=int(tags[1])
atom=noesy.Atom(tags[2],int(tags[5]))
atomx=float(tags[6])
atomy=float(tags[7])
atomz=float(tags[8])
obj=PDBAttributes(atomindex, atom, atomx, atomy, atomz)
print obj
class AtomDistance(PDBAttributes):
def distance(self, atom1,atom2):
pass
The NameError you are getting is due to the order you have placed the code in your file.
When you call read_structure to create a value for the pdb variable, it tries to look for PDBAttributes, but it has not been defined yet. If you move that line lower down in the file (below the class definition) you'll avoid that error. Note that it is OK to have the declaration of read_structure above the PDBAttributes class definition, though you might want to move it lower too to make the code easier to understand.
Here's a very simple bit of code that demonstrates the same error:
def foo():
print(foo_text)
foo() # raises a NameError
foo_text = "foo"
Here's a fixed version:
def foo():
print(foo_text)
foo_text = "foo"
foo() # no error, prints "foo"
Move your call of read_structure to follow the definition of the PDBAttributes class.
Also, in the process of reformatting your post, I see that you have mixed tabs and spaces for your indentation. Try reformatting your code to use all spaces for indentation, the recommended form is 4-space indents.
Your definition of all those getter functions looks like Java written in Python - this is a lot of extra code that is often unnecessary in Python. The recommended approach is to omit these all-they-do-is-assign-a-value-to-an-attribute-with-the-same-name-but-with-a-leading-underscore methods and just use attributes with the public names. See Python is Not Java.

NameError: global name 'thing' is not defined

I don't think there is quite the need for the continued downvoting, I am just trying to learn here!
One.py
from two import *
ADooDah = Doodah()
something = Thing(ADooDah)
something.DoThis()
something.DoThat
something.DoAnother
if (something.has_done_stuff() == True)
self.SomeFunction
Two.py
class Thing(var):
def __init__(self, var)
self.SomeVar = var
def has_done_stuff(self):
while True:
id, newMessage = SomeVar.get_next_message()
if id == 0:
return true
else:
return false
I get...
Traceback (most recent call last):
File "C:\One.py", line 9, in <module>
has_done_stuff = thing.HasDoneStuff()
NameError: global name 'thing' is not defined
EDITS: The code was indeed peppered with errors. I was trying to show my situation rather than any real code. Rush typing causes foolish typing. Even I'm not that bad! Well, most of the time ;) .
I hope the edits make it all make more sense and you fine people can stop focusing on the crazy syntax errors and explain a bit more about my scope (I assume) problem. I'm fairly new to Python/IronPython and the rules around implicit types and scoping I am still in the process of learning!
I have solved my problem though. Thanks. It was fairly unrelated to the above as it turns out.
Something = Thing(ADooDah)
thing.DoThis()
Your thing is called Something.
Also, your class Thing has none of the methods you are calling/not calling (missing parens). This is pretty much non-sense code.
There are a few issues:
You claim Thing is defined in Two.py. If so, you need to import it thus:
from Two import Thing
or (not recommended):
from Two import *
Next, you need class, not Class.
Next, you need to define thing, which you haven't done. I will take a wild guess that you want thing to be a Thing object:
thing = Thing(ADooDah)
then there is the pfoblem with the if inside HasDoneStuff that someone has referred to in a comment, and the fact that Thing is incomplete (also mentioned in another answer).
I give the following codes.
I don't know for what they will be usable...... But they CAN run.
.
two.py
from time import time
class Thing():
def __init__(self, var):
self.SomeVar = enumerate(var)
def HasDoneStuff(self):
while True:
id, newMessage = self.SomeVar.next()
print newMessage
print 'id==',id
return id == 0
def DoThis(self):
print "DoThis' result"
def DoThat(self):
print 'DoingThat ;;;;;;;;;;;;;;;;;;;;;'
def DoAnother(self):
print 'DoAnother time',time()
def SomeFunction(self):
print 'Humpty Dumpty sat on a wall'
.
one.py
from two import *
def Doodah(ss):
return ss.split()
ADooDah = Doodah('once upon a time')
Something = Thing(ADooDah)
Something.DoThis()
Something.DoThat()
Something.DoAnother()
print '\n==========================\n'
while True:
try:
if Something.HasDoneStuff():
Something.SomeFunction()
print '---------------'
except StopIteration:
print "That's all folks"
break

Categories