I writing HTML to a text file which is then read by the browser, but I get an error stating "not all arguments converted during string formatting"
But i can't see hwere im going wrong.
z.write('<td><a href=/Plone/query/species_strain?species=%s>'+k+'</td>' % k)
You're missing parentheses:
z.write(('<td><a href=/Plone/query/species_strain?species=%s>'+k+'</td>') % k)
But it would be better not to mix concatenation and formatting. So consider:
'<td><a href=/Plone/query/species_strain?species=%(k)s>%(k)s</td>' % {'k': k}
You might want to generate HTML using a dedicated tool. Concatenating strings tends to lead to buggy and hard to parse HTML.
You're using string concatenation in combination with substitution. Your substitution formatter %s is in the first string, but the % k applies to the last. You should do this:
'<td><a href=/Plone/query/species_strain?species=%s>%s</td>' % (k,k)
Or this:
('<td><a href=/Plone/query/species_strain?species=%s>'+k+'</td>') % k
You get wrong and combining + and string formatting through %. If k contains any %-sequence it would look like this:
'<td...species=%s>...%s...</td>' % k
You get two or more %-sequences and only one argument. You probably want this instead:
'...species=%s>%s</td>' % (k, k)
% k must be after string with %s
z.write('<td><a href=/Plone/query/species_strain?species=%s>' % k +k+'</td>')
or better
z.write('<td><a href=/Plone/query/species_strain?species=%s>%s</td>' % (k, k))
Related
Right now I have the method below, it works perfectly fine but I want to change part of the self.wait_for_element(....) to instead use %s rather than calling str(counter)
> def gather_recent_visited_courses_in_content_switcher(self):
hover_courses = self.browser.find_elements_by_xpath("//div[contains(#class, 'recent-content flyout-closed')]")
course_list = []
counter = 1
for course in hover_courses:
self.hover_over(course)
# Change the below to %s
self.wait_for_element("//div[contains(#class, 'fly-wrapper recent-content-trigger')][" + str(counter) + "]//div[contains(#class, 'recent-content-info')]", 'Course list not found')
course_display_name = course.find_element_by_xpath("//div[contains(#class, 'recent-content-info')]").text
course_list.append(str(course_display_name))
counter += 1
return course_list
Currently I keep getting errors when replacing it with [%s], like below
> self.wait_for_element("//div[contains(#class, 'fly-wrapper recent-content-trigger')][%s]//div[contains(#class, 'recent-content-info')]", 'Course list not found' %(counter))
Does anyone have any ideas on how to get this to work properly? So far, I keep getting 'not all arguments converted during string formatting' errors
The reason why using %s isn't working is because you are setting the placeholder value in the second string argument, and not the first string as you have intended.
With the first argument:
"//div[contains(#class, ...)][%s]//div[... 'recent-content-info')]"
Python can't find the proper value to replace %s with in the first string argument. So, that will raise an error.
As for the second argument:
'Course list not found' % (counter)
You are passing a value to the string but the string cannot be formatted to use the passed value because the string doesn't have placeholder, %s. So, that'll raise an error too.
To fix that, just format the first string argument. It'll look like this:
"//div[contains(#class, '...')][%s]//div[..., 'recent-content-info')]" % counter
Alternatively, you can use .format(). This the new style of string formatting. Using %s is considered to be the old style[1].
"//div[contains(#class, '...')][{}]//div[..., 'recent-co...')]".format(counter)
NOTE: Strings have been redacted to make things easier to read.
References
[1] - https://pyformat.info/
What is the difference between defining a variable and using it in a string and putting %s in a string and passing in the value after?
site = "Stackoverflow"
site + " is great!"
"%s is great!" % "Stackoverflow"
Printing either of these gives the same result so when is it better to use one over the other?
If you want to keep certain string constants in the same file, or on the top most of the file, you can declare the string with the placeholders as constants, then replace the placeholders with actual variable at run time through the % syntax.
This also allows greater re-usability.
Eg. you can store a single constant "%s is %s years old".
Using this syntax might also make the string more readable.
For two strings, there is little difference.
For multiple strings, s1 + s2 + s3 is less efficient, as it has to create a temporary str object for the first concatenation, where as both "%s %s %s" % (s1, s2, s3) and "{} {} {}".format(s1, s2, s3) creates the final str object immediately.
One:
'string' + 'string'
Two:
'%s %s' % ('one', 'two')
'{} {}'.format('one', 'two')
There is a great article on this here: https://pyformat.info/
Also the docs are a great resource: https://docs.python.org/2/library/string.html#format-string-syntax
Version one is less efficient with larger amounts of concatenation.
I am using Python 2.7 and Django 1.6.11 for my project and I want iterating to get a list of params with code like this:
for idx in range(1, int(number_unit_orders) + 1):
is_edit = request.POST.get('edit_%s'.format(str(idx)))
# Do something with is_edit
But the is_edit is always None although edit_1 and so on are set in the request object. But the code block below works(use string concatenation):
for idx in range(1, int(number_unit_orders) + 1):
is_edit = request.POST.get('edit_' + str(idx))
# Do something with is_edit
Wonder why this is the case.
'edit_%s'.format(str(idx))
Is mixing up two different types of formatting
You need to choose one of them and stick to it
'edit_%s' % str(idx) # 'edit_%d % idx
'test_{}'.format(idx)
The reason you're getting none is because you're trying to get an object that doesn't exist, it is actually currently looking up the exact string of edit_%s
In format method you don't use % but {}.
Please rewrite your line with this method to:
is_edit = request.POST.get('edit_{}'.format(idx))
Also explicit str is not needed.
Format doesn't work like that. Your code should be:
'edit_{0}'.format(str(idx))
How do I replace %s with a defined/non-empty variable string? Or rather what is the Pythonic or syntactic sugar for doing so?
Example:
# Replace %s with the value if defined by either vehicle.get('car') or vehicle.get('truck')
# Assumes only one of these values can be empty at any given time
# The get function operates like http://docs.python.org/2/library/xml.etree.elementtree.html#xml.etree.ElementTree.Element.get
logging.error("Found duplicate entry with %s", vehicle.get('car') or vehicle.get('truck'))
I think you want this:
'Found duplicate entry with %s' % (vehicle.get('car') or vehicle.get('truck'))
This will replace the '%s' with the non-empty string (assuming only one is non-empty). If both contain text, it will be replaced with the output of vehicle.get('car')
You could also use this type of string formatting:
'Found duplicate entry with {0}'.format(vehicle.get('car') or vehicle.get('truck'))
This will return the same result.
Have you tried something like this?
logging.error("Found duplicate entry with %s" % (vehicle.get('car') or vehicle.get('truck')))
Or if truck is also empty, you can return a default value:
logging.error("Found duplicate entry with %s" % (vehicle.get('car') or vehicle.get('truck', 'default')))
In Python 2.7.1 I can create a named tuple:
from collections import namedtuple
Test = namedtuple('Test', ['this', 'that'])
I can populate it:
my_test = Test(this=1, that=2)
And I can print it like this:
print(my_test)
Test(this=1, that=2)
but why can't I print it like this?
print("my_test = %r" % my_test)
TypeError: not all arguments converted during string formatting
Edit:
I should have known to look at Printing tuple with string formatting in Python
Since my_test is a tuple, it will look for a % format for each item in the tuple. To get around this wrap it in another tuple where the only element is my_test:
print("my_test = %r" % (my_test,))
Don't forget the comma.
You can do this:
>>> print("my_test = %r" % str(my_test))
my_test = 'Test(this=1, that=2)'
It's unpacking it as 2 arguments. Compare with:
print("dummy1 = %s, dummy2 = %s" % ("one","two"))
In your case, try putting it in a tuple.
print("my_test = %r" % (my_test,))
The earlier answers are valid but here's an option if you don't care to print the name. It's a one-liner devised to pretty print only the contents of a named tuple of arbitrary length. Given a named tuple assigned to "named_tuple" the below yields a comma-delineated string of key=value pairs:
', '.join(['{0}={1}'.format(k, getattr(named_tuple, k)) for k in named_tuple._fields])
As now documented at 4.7.2. printf-style String Formatting, the % string formatting or interpolation operator is problematic:
The [printf-style string formatting operations] 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 formatted string literals or the str.format() interface helps avoid these errors
So for example you can now do:
from collections import namedtuple
Test = namedtuple('Test', ['this', 'that'])
my_test = Test(this=1, that=2)
print("my_test = {0!r}".format(my_test))