2

I'm trying to create a class to connect to box using pexpect and grab some data from that box, and I have difficulty of creating a function that contains the pexpect session for my box and initializes it for each object that I create in the class code example below.

class A:
   def __init__(self)
       # in this way a session will be created for each object and i don't 
       # need that i need only one session to open for any object created.
       session = pexpect.spawn('ssh myhost')
       session.expect('myname@myhost#')

   def get_some_data(self,command)
       session.sendline(command)
       session.expect('myname@myhost#')
       list = session.before.splitlines()
       return list

now my problem is if I do create a new object a new session will be created for each object, and that is not required I can use only one session for every object I create from this class

zdim
  • 64,580
  • 5
  • 52
  • 81
MRM
  • 23
  • 3

1 Answers1

3

You can use a class method to connect and set a class variable for the pexpect's instance (child). Then instance methods in this class can use that class variable

import pexpect

class Comms:
    Is_connected = False
    Name = None
    ssh = None

    @classmethod
    def connect(cls, name):
        cls.Name = name
        cls.ssh = pexpect.spawn('ssh ' + name)
        cls.ssh.expect('password:')
        cls.ssh.sendline('*****')
        cls.ssh.expect('> ')
        print cls.ssh.before, cls.ssh.after
        cls.Is_connected = True

    @classmethod
    def close(cls):
        cls.ssh.close()
        cls.ssh, cls.Is_connected = None, False

    def check_conn(self):
        print self.Name + ' is ' + str(self.Is_connected)
        return self.Is_connected

    def cmd(self, command):
        self.ssh.sendline(command)
        self.ssh.expect('> ')
        return self.ssh.before + self.ssh.after

The self.ssh used in instance methods is a way to use a class variable inside the class, if it is not assigned to. If it were assigned to that would instead create an instance variable with the same name. In this case that should not happen since there is no reason to assign to ssh in this class.

A class method receives the class as an implicit argument so cls.ssh can be used. Inside an instance method one can also get a reference to the class and then use cls.ssh

def cmd(self, command):
    cls = self.__class__
    cls.ssh.sendline(command)
    ...

A class variable can be used anywhere as Comms.ssh. This is a rather bare-bones class.

Now connect to a host using the class method and run commands via different instances

from comms import Comms

userathost = 'xxx@xxxxx'

print 'Connect to ' + userathost
Comms.connect(userathost)

conn_1 = Comms()
conn_1.check_conn()
print conn_1.cmd('whoami')
print

conn_2 = Comms()
print 'With another instance object: pwd:'
print conn_2.cmd('pwd')

Comms.close()

With a real userathost, and redacted for personal details in [description], this prints

Connect to xxx@xxxxx

Last login: Sat Aug 12 01:04:52 2017 from *****
[... typical greeting on this host]
[my prompt] > 
xxx@xxxxx is True
whoami
[my username]
[my prompt] > 

With another instance object: pwd:
pwd
[path to my home]
[my prompt] > 

The connection should be set up and output handled more nicely, but that's about pexpect.


For class/static methods and variables see, for instance

zdim
  • 64,580
  • 5
  • 52
  • 81