Python Forum
How do I call sys.argv list inside a function, from the CLI?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How do I call sys.argv list inside a function, from the CLI?
#1
So I wrote some code and it works fine but I am having issues passing in classes/functions from the command line.

Here's the code:
import sys
import netmiko
import json

from Hardware_info import HardwareMaintenance

Hardware = HardwareMaintenance.hardware_handler


class Connect:
    def __init__(self, **kwargs):
        # self.protocol = netmiko.ssh_autodetect
        # pass
        intake_file = open('ip_list.txt', 'r')
        self.json_data = [json.loads(line) for line in intake_file]
        self.kwargs = [Hardware]

    def connect_parser(self, kwargs=None):

        for data in self.json_data:
            ip = data["ip"]
            # port = data["port"]
            username = data["username"] if data["username"] else ""
            password = data["password"] if data["password"] else ""
            secret = data["secret"] if "secret" in data else False
            device_type = data["device_type"] if data["device_type"] else ""

            if data["header"] == "Netmiko":
                print("The variables being passed:  " + ip, username, password, device_type)
                ConnectHandler = netmiko.ConnectHandler(
                    device_type=device_type,
                    host=ip,
                    username=username,
                    password=password,
                    port=22,
                    secret=data["secret"] if "secret" in data else False
                )
                ConnectHandler.enable()
when I add this line next under ConnectHandler.enable() it works:
Hardware(ConnectHandler,ip)

Hardware is another class which reads in ip from the above code and performs some operations.
Everything is working fine.

Now I want to try to call Hardware from the cli, as I will be having up to 5-10 seperate classes that will be performing operations on ConnectHandler and ip, i.e class_n(ConnectHandler, ip)

and I want to pick and choose classes from the cli.


And so I did this:
if __name__ == "__main__":
    from Connect_Handler import Hardware
    from Connect_Handler import Connect
    Connector = Connect()
    inlist = sys.argv[0]
    Connector.connect_parser(inlist)
I also added this into the main script under ConnectHandler.enable()
 for i in kwargs:
                    i(ConnectHandler)
where kwargs are variables to be passed into connect_parser

notice how I imported Hardware above. I am ok with that, that isn't the problem, as i will be importing multiple classes whether here or in the main.py file, and I want to define which classes to use in a list in the command line. Hardware is a class. It work fine when I executed it in the Connect class.


here's me trying to execute it from the CLI:


py Connect_Handler.py inlist = [Hardware]

notice i passed in inlist as sysargv, and I want it to operate like kwargs in connect_parser.

The output gives me 'str' object is not callable


so then i change the name == __main__ section to:

if __name__ == "__main__":
    from Connect_Handler import Hardware
    from Connect_Handler import Connect
    Connector = Connect()
    inlist = sys.argv[0]
    for i in inlist:
        i(Connector.connect_parser())
again it gives me 'str' object is not callable



and so i tried this, and printed out the 'type' of my functions to have a look at them, and realised that Connector.connect_parser() resolves to a NoneType:

if __name__ == "__main__":
    from Connect_Handler import Hardware
    from Connect_Handler import Connect
    Connector = Connect().connect_parser()
    print(Connector)
    inlist = sys.argv[0]
    Connector.Connect(inlist)
CLI:
py Connect_Handler.py [Hardware]


and it gives me
"NoneType has no attribute Connect"




Can some one guide me either to what to do or where to experiment to try and resolve this issue? In the end all I need to do is call Hardware on the ConnectHandler from the CLI

Hardware(ConnectHandler)

by passing it to connect_parser
connect_parser(Hardware)

as I plan on passing a list of imported functions from the CLI when i run this.
Reply
#2
I tried to define the sys.argv within the class itself, and I still get TypeError 'str' object is not callable.
import sys
import netmiko
import json

from Hardware_info import HardwareMaintenance

Hardware = HardwareMaintenance.hardware_handler


class Connect:
    def __init__(self, **kwargs):
        # self.protocol = netmiko.ssh_autodetect
        # pass
        intake_file = open('ip_list.txt', 'r')
        self.json_data = [json.loads(line) for line in intake_file]
        self.kwargs = [Hardware]

    def connect_parser(self, inlist=[]):
        inlist = sys.argv[0]
        for data in self.json_data:
            ip = data["ip"]
            # port = data["port"]
            username = data["username"] if data["username"] else ""
            password = data["password"] if data["password"] else ""
            secret = data["secret"] if "secret" in data else False
            device_type = data["device_type"] if data["device_type"] else ""

            if data["header"] == "Netmiko":
                print("The variables being passed:  " + ip, username, password, device_type)
                ConnectHandler = netmiko.ConnectHandler(
                    device_type=device_type,
                    host=ip,
                    username=username,
                    password=password,
                    port=22,
                    secret=data["secret"] if "secret" in data else False
                )
                ConnectHandler.enable()
                for i in inlist:
                    i(ConnectHandler,ip)

if __name__ == "__main__":
    from Connect_Handler import Hardware
    from Connect_Handler import Connect
    print(Connect().connect_parser())
    inlist = sys.argv[0]
    #Connector.Connect(inlist)

# def runner():
#    #for i in sys.argv[0]:
#   Hardware(Connector.)
# runner()
notice I added

                for i in inlist:
                    i(ConnectHandler,ip)
to the end under ConnectHandler.enable()

and it's giving me the TypeError 'str' object is not callable
whether or not I pass in a list for sys.argv[0] in the command line.



however when I change inlist to:

    def connect_parser(self, inlist=[]):
        inlist = [Hardware]
notice i included Hardware


and now it is working fine. I don't want to be able to do this by passing in a list in the CLI...

I tried
    def connect_parser(self, inlist=[]):
        inlist = sys.argv[0]
and no go
Reply
#3
I read online the command list in windows reads everything in as a string.
So I changed my __name__ == __main__ to below and it works, as I had to sstrip and split the argument into a list and map it back to a dictionary which stored functions.

I'm sure there's ways to make the code more precise, maybe using a map function, but it is working now.

functions = {'Hardware': Hardware}


if __name__ == "__main__":
    from Connect_Handler import Hardware
    from Connect_Handler import Connect
    inlist = sys.argv[1]
    outlist = inlist.strip("[]").split(",")
    inlist = []
    Connector = Connect()
    for i in outlist:
        inlist.append(functions[i])
    Connector.connect_parser(inlist)
Reply
#4
Better use the arparse module from the standard library to handle CLI arguments
import argparse

class Hardware:
    pass
class Spam:
    pass
class Eggs:
    pass

if __name__ == '__main__':
    functions = {'Hardware': Hardware,
                 'Spam': Spam,
                 'Eggs': Eggs}

    parser = argparse.ArgumentParser()
    parser.add_argument(
        '--connect', '-c',
        choices=functions.values(),
        nargs='*',
        action='extend',
        dest='inlist',
        type=functions.get)
    ns = parser.parse_args()
    print(ns.inlist)
    for f in ns.inlist:
        f()
Output:
$ python paillasse/pf/billy.py -c Hardware Eggs [<class '__main__.Hardware'>, <class '__main__.Eggs'>]
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  for loops break when I call the list I'm looping through Radical 4 906 Sep-18-2023, 07:52 AM
Last Post: buran
  with open context inside of a recursive function billykid999 1 587 May-23-2023, 02:37 AM
Last Post: deanhystad
  sys.argv method nngokturk 3 1,091 Jan-23-2023, 10:41 PM
Last Post: deanhystad
  Need to parse a list of boolean columns inside a list and return true values Python84 4 2,125 Jan-09-2022, 02:39 AM
Last Post: Python84
  how to call an object in another function in Maya bstout 0 2,089 Apr-05-2021, 07:12 PM
Last Post: bstout
  import argv Scott 3 5,914 Apr-01-2021, 11:03 AM
Last Post: radix018
  In this function y initially has no value, but a call to foo() gives no error. Why? Pedroski55 8 3,508 Dec-19-2020, 07:30 AM
Last Post: ndc85430
  How to make global list inside function CHANKC 6 3,123 Nov-26-2020, 08:05 AM
Last Post: CHANKC
  How to create a linked list and call it? loves 12 4,539 Nov-22-2020, 03:50 PM
Last Post: loves
  Struggling for the past hour to define function and call it back godlyredwall 2 2,233 Oct-29-2020, 02:45 PM
Last Post: deanhystad

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020