rummonkey rummonkey - 2 years ago 95
Python Question

Python print: error with string formatting

I have been trying to incorporate boto3 into my AWS workflow after using fabric for a little while. Just started learning Python so apologies in advance for some of these questions. I searched and debugged what I could with the below script as most of the errors seemed prior seemed to be with this being written in Python2 and I am using Python3 on OSX. Sorry for the formatting issues as well tried to get the script into a code block for here.

#!/usr/bin/env python
import boto3
import sys
import argparse
import paramiko

def list_instances(Filter):
ec2 = boto3.resource('ec2')
instances = ec2.instances.filter(Filters=Filter)
columns_format = ("%-3s %-26s %-16s %-16s %-20s %-12s %-12s %-16s")
print (columns_format) ("num", "Name", "Public IP", "Private IP", "ID",
"Type", "VPC", "Status")
num = 1
hosts = []
name = {}
for i in instances:
name = (item for item in i.tags if item["Key"] == "Name" ).next()
except StopIteration:
name['Value'] = ''

print (columns_format) % (
num = num + 1
item={'id':, 'ip': i.public_ip_address, 'hostname':
name['Value'], 'status': i.state['Name'],}

return hosts

def execute_cmd(host,user,cmd):
ssh = paramiko.SSHClient()
ssh.connect(host, username=user)
stdin, stdout, stderr = ssh.exec_command(cmd)
return stdout,stderr
except paramiko.AuthenticationException as exception:
return "Authentication Error trying to connect into the host %s with the user %s. Plese review your keys" % (host, user), e

def main():
parser = argparse.ArgumentParser()
parser.add_argument('-n', '--name',
help="Filter result by name.")
parser.add_argument('-t', '--type',
help="Filer result by type.")
parser.add_argument('-s', '--status',
help="Filter result by status." )
parser.add_argument('-e', '--execute',
help="Execute a command on instances")
parser.add_argument('-u', '--user', default="ubuntu",
help="User to run commands if -e option is used.\
Ubuntu user is used by default")

arg = parser.parse_args()

# Default filter if no options are specified

filter.append({'Name': 'tag-value', 'Values': ["*" + + "*"]})

if arg.type:
filter.append({'Name': 'instance-type', 'Values': ["*" + arg.type + "*"]})

if arg.status:
filter.append({'Name': 'instance-state-name', 'Values': ["*" + arg.status + "*"]})

names = ""

if arg.execute:
for item in hosts:
names = names + " " + item["hostname"] + "(" + item["id"] + ")"
print ("\nCommand to execute: %s") % arg.execute
print ("Executed by: %s") % arg.user
print ("Hosts list: %s\n") % names
for item in hosts:
if item["status"] == 'running':
print ("::: %s (%s)") % (item["hostname"], item["id"])
stdout,stderr = execute_cmd(item["ip"], arg.user, arg.execute)
print (stdout)
print (stderr)
print ("::: %s (%s) is not running (command execution skiped)") % (item["hostname"], item["id"])

if __name__ == '__main__':

Excuted from terminal: python

and get the below output:

%-3s %-26s %-16s %-16s %-20s %-12s %-12s %-16s
Traceback (most recent call last):
File "", line 97, in <module>
File "", line 78, in main
File "", line 12, in list_instances
print (columns_format) ("num", "Name", "Public IP", "Private IP", "ID",
"Type", "VPC", "Status")
TypeError: 'NoneType' object is not callable

Thanks in advance for the help!

Answer Source

I think your problem is just that you can't call print like this:

print (columns_format) ("num", "Name", "Public IP", "Private IP", "ID", 
"Type", "VPC", "Status")

because print(arguments) (arguments) tries to call a function

try to replace it with (i guess the % just got lost)

print ((columns_format) % ("num", "Name", "Public IP", "Private IP", "ID", 
"Type", "VPC", "Status"))
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download