Reputation: 2075
Hi I would like to know how do I pass obeject between classes. I'm going to use my script to first login to our server, next to client server and than to the routers and switches. Here is the script: the file name is connect.py:
import expect
class domain_connect:
def __init__(self,usr='user',pwd='password',d1='192.168.1.3',dclient='192.168.2.3'):
self._usr =us
self._pwd =pwd
self._d1 =d1
self._dclient =dclient
def djump(self):
child=pexpect.spawn('ssh -o StrictHostKeyChecking=no -l ' +self._usr+" "+self._d1)
child.expect('assword:')
child.sendline(self._pwd)
child.expect(':~>')
##Connect to client server
child.sendline(self._dclient)
child.expect('assword:')
child.sendline(self._pwd)
child.expect('accept:')
child.sendline(' ')
child.expect(':~>')
return child
class ce_connect:
def __init__(self, child, ip, usr, pwd, enpwd):
self._child = child
self._ip = ip
self._usr = usr
self._pwd = pwd
self._enpwd = pwd
def cjump(self):
##Connecting to router
child.sendline('ssh -o StrictHostKeyChecking=no -l '+self._usr+' '+self._ip)
return self._child
Here is the script that use:
import connect
child = connect.domain_connect()
child = child.djump() ## At this point I'm good toward the client server
I was trying to do the following to pass the child object to the ce_connect class
child2 = connect.ce_connect(child, '192.78.1.20', 'username', 'password', 'password2')
child2 = child2.cjump()
I get an error:
AttributeError: 'spawn' object has no attribute 'djump'
Upvotes: 2
Views: 5938
Reputation: 365915
You already are successfully passing the child
object to the ce_connect
constructor.
When you do this:
child2 = connect.ce_connect(child, '192.78.1.20', 'username', 'password', 'password2')
… that passes child
to the ce_connect
constructor, so child2._child
ends up being the same object as child
. So, when you call child2.cjump()
, and that calls self._child.dump()
, it's calling djump
on your child
object. Just as it should.
The problem is that child
isn't a domain_connect
object, it's a pexpect.spawn
object. That's why you get that AttributeError: 'spawn' object has no attribute 'djump'
, which means exactly what it says.
The reason for that is simple:
child = child.djump()
This sets child
to whatever djump
returns. What djump
returns is a pexpect.spawn
object. Before that line, child
was a domain_connect
, but now, it's a spawn
, and you no longer have any accessible reference to the domain_connect
.
The answer is simple: don't do that. Keep a reference to the domain_connect
, and use it. Something like this:
child = connect.domain_connect()
child_jump = child.djump()
child2 = connect.ce_connect(child, '192.78.1.20', 'username', 'password', 'password2')
child2_jump = child2.cjump()
As a side note, I think reusing the name child
inside the method implementation and in the calling code is confusing you. It's easier to keep things straight if you can come up with distinct names.
Meanwhile, once you fix this, you have another problem. Your code seems to expect the child
of a ce_connect
to be both a domain_connect
and a pexpect.spawn
at the same time. In particular, inside ce_connect.cjump
, you've got this:
child.sendline('ssh -o StrictHostKeyChecking=no -l '+self._usr+' '+self._ip)
There's no sendline
method of a domain_connect
object.
It's hard to decide what the right fix is here. You need to get straight in your head what each of these objects is supposed to be. Why are they all called child
? What is a child supposed to mean?
One possibility is that the child
objects are supposed to be the pexpect
child processes, not the *_connect
objects, so what you really want is something like this:
domain = connect.domain_connect()
child = domain.djump()
ce = connect.ce_connect(child, '192.78.1.20', 'username', 'password', 'password2')
child2 = ce.cjump()
Or, maybe you actually have no use for these connect
objects at all, just the results of their djump
/cjump
methods. In which case you could write it as:
child = connect.domain_connect().djump()
child2 = connect.ce_connect(child, '192.78.1.20', 'username', 'password', 'password2').cjump()
But in that case, you'd probably be better off making the public interface be a pair of module-level functions, and hide the classes under the implementation of those functions.
Or, maybe you want to let the domain_connect
objects act as child processes on top of whatever else they represent, by holding onto the result of djump
as a _child
member, then delegating sendline
, and maybe other methods, to the real pexpect
object, like this:
def sendline(self, line):
return self._child.sendline(line)
Or… well, as I said, there are many possibilities, and without knowing how your design is supposed to work and what your classes and variables are supposed to represent, there's really no way to say how to make your code fit your design.
Upvotes: 5