Python- best way to pass variable arguments to subprocess.call - python

I am trying to use a python script to call an external command a number of times, each time with a different variable.
I see there are recommendations to use subprocess.call to do this, however all the documentation I have found doesn't explain how to pass this function variables (from a list for example).
I have tried a number of different formats, and I think a substitution would be the best, but it seems like the function wont accept the variable.
The code I am trying to get working is:
#!/usr/bin/python
domain_list = ["google.com", "google.ie"]
from subprocess import call
for x in domain_list:
print x
cmd_list = ['dig', '+short', '%s'] %x
call(cmd_list, shell=True)
This is failing with:
Traceback (most recent call last):
File "./dnscheck.py", line 16, in <module>
cmd_list = ['dig', '+short', '%s'] %arg
TypeError: unsupported operand type(s) for %: 'list' and 'str'
Really I want to be able to pass a bunch of different domains (defined in a list) to dig and receive the IP's of those domains.
I've just started with python so sorry if this is very basic!

You are trying to use the modulo operator on a list, I presume you wanted to do string formatting on the last item, as the percentage symbol is overloaded to do formatting with strings, but as you just want to insert the item without any formatting, you can just give it directly:
['dig', '+short', x]
If you did want to use formatting, you would need to do it on the string:
['dig', '+short', '%s' % x]
Note however, that this is pointless given you are not doing any formatting.

Related

Slicing a string from inside a formatted string gives 'TypeError: string indices must be integers'

Shouldn't both these commands do the same thing?
>>> "{0[0:5]}".format("lorem ipsum")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: string indices must be integers
>>> "{0}".format("lorem ipsum"[0:5])
'lorem'
The commands
>>> "{0[0]}".format("lorem ipsum")
'l'
and
>>> "{0}".format("lorem ipsum"[0])
'l'
evaluate the same. (I know that I can use other methods to do this, I am mainly just curious as to why it dosen't work)
The str.format syntax is handled by the library and supports only a few “expression” syntaxes that are not the same as regular Python syntax. For example,
"{0[foo]}".format(dict(foo=2)) # "2"
works without quotes around the dictionary key. Of course, there are limitations from this simplicity, like not being able to refer to a key with a ] in it, or interpreting a slice, as in your example.
Note that the f-strings mentioned by kendall are handled by the compiler and (fittingly) use (almost) unrestricted expression syntax. They need that power since they lack the obvious alternative of placing those expressions in the argument list to format.

Use Python reserved words in an XML File

I'm currently trying to use python's (3.6) xml.etree.ElementTree commands to write an xml file. Some of the Elements and Subelements I need to write must have "id" and "map" fields, which are reserved python words.
My problem is contained in the following line of code:
ET.SubElement(messages,'trigger',thing='1',bob='a', max='5')
But "max" is a function and I can't use it. Is there a character I can place there to allow me to write this field as I desire? Or some sort of known workaround?
EDIT: I am aware that an '_' stops the python from processing the word, but unfortunately this underscore will show up in my file...so I am trying to see if there is an 'invisible' option for the file I will later be writing.
Thanks much!
Python functions are no problem in the left side of a keyword expression:
>>> def abc(**kwargs):
print kwargs
>>> abc(id=2)
{'id': 2}
>>>
id, map, int, float, str, repr, etc. are built in symbols, not reserved words. You may use them like any other bunch of letters, but assigning it another value replaces the built in symbol:
>>> int(2.5)
2
>>> int = "5"
>>> int(2.5)
Traceback (most recent call last):
File "<pyshell#10>", line 1, in <module>
int(2.5)
TypeError: 'str' object is not callable
Notice how the first line is entirely legal, but will trigger a warning if you have a good IDE like pycharm.
If you want to send a actual reserved word to a function, like print, None, yield, or try, you can use the double star ** to convert a dictionary into keyword arguments, for example:
>>> abc(**{"print":2, "None":3})
{'print': 2, 'None': 3}
I hope this answers your question!

Printing mixed list in python

I am using Python 3.6. I am using Learn Python the hard way as reference.
I have a mixed list and I am trying to print the elements. The books says to use
format code "r" since we don't know what's in the list. But I am getting error with this.
Was this working in previous versions? How can I print mixed list, each element a time.
Here is my code and error:
change = [1,'pennies',2,'dimes',3,'quarters']
for i in change:
print("I got {:r}".format(i))
Error Stack trace:
Traceback (most recent call last):
File "<pyshell#52>", line 2, in <module>
print("I got {:r}".format(i))
ValueError: Unknown format code 'r' for object of type 'int'
Thanks
For str.format, the "force to repr" conversion is done with !r. not :r; it's not asserting a type for conversion, it's saying "don't use __format__ at all, use __repr__ to perform the conversion". Make it:
print("I got {!r}".format(i))

How do you print two variables within brackets in Python 3?

I have this line of code:
print ("(x %s)(x %s)") % (var_p1, var_p2)
But it does not work, I am new to programming and I don't know what I have done wrong. Any experts out there with a simple answer?
I wanted it to randomly select an equation for a parabola. e.g. (x-3)(x+1) However, it comes up with the error message:
Traceback (most recent call last):
"File "E:/Python34/MyFiles/Math Study Buddy.py", line 26 in <module>
print ("(x %s)(x %s)") % (var_p1, var_p2)
TypeError: unsupported operand type (s) for %: 'NoneType' and 'tuple'
As you are in python 3 you need to put the variables inside the parenthesis after your string:
>>> print ("(x %s)(x %s)"%(2, 3))
(x 2)(x 3)
Note that in python 3 print is a function and you need to pass the string as its argument.So you can not put your variables outside the function!
For more detail read printf-style String Formatting
Note
The formatting operations described here exhibit a variety of quirks that lead to a number of common errors (such as failing to display tuples and dictionaries correctly). Using the newer str.format() interface helps avoid these errors, and also provides a generally more powerful, flexible and extensible approach to formatting text.
You can use str.format
>>> var_p1 = 'test'
>>> var_p2 = 'test2'
>>> print(("(x {})(x {})".format(var_p1, var_p2)))
(x test)(x test2)
you don't need to use 'x' to substitude variables here.
This will fix:
print ("(%s)(%s)") % (var_p1, var_p2)
also, .format is better than %
see:
Python string formatting: % vs. .format

argv in python not working with windows executable cmdline [duplicate]

This question already has answers here:
How do I parse a string to a float or int?
(32 answers)
Closed 20 days ago.
in windows: I would like this program to run on commandline. However, I am getting an error. What am I doing wrong?
# create a method that append the letter stored in variable letter, ntimes.
import sys
def appender(letter,ntimes, sentence):
print sentence+(letter*ntimes)
appender(str(sys.argv[1]),sys.argv[2], str(sys.argv[3]))
The below is the error i get from command line in windows
C:\Users\QamarAli\Documents\afaq's stuff>appender.py "F" 10 "Hello this is sent"
Traceback (most recent call last):
File "C:\Users\QamarAli\Documents\afaq's stuff\appender.py", line 8, in <modul
e>
appender(str(sys.argv[1]),sys.argv[2], str(sys.argv[3]))
File "C:\Users\QamarAli\Documents\afaq's stuff\appender.py", line 5, in append
er
print sentence+(letter*ntimes)
TypeError: can't multiply sequence by non-int of type 'str'
C:\Users\QamarAli\Documents\afaq's stuff>
The error is pretty clear:
TypeError: can't multiply sequence by non-int of type 'str'
You're trying to multiply a sequence (in this case, a string) by something that isn't a number. Convert your argument to an integer:
appender(sys.argv[1], int(sys.argv[2]), sys.argv[3])
Also, sys.argv arguments are strings by default, so there's no need to explicitly convert them again.
The values in sys.argv are all strings. Instead of trying to convert some to strings, you need to convert the other ones to whatever non-string types you need. If you want the middle one to be an integer, call int on it.
All commandline arguments are seen by Python as strings.
Change your call to
appender(sys.argv[1], int(sys.argv[2]), sys.argv[3])

Categories

Resources