So I had already updated PIP prior to [Kevin Adler's] reply. Should I try to uninstall PIP and reinstall via YUM, or just leave well enough alone?
I will let him answer that, as he's the expert.
I do have a lot of comments about Python, though:
Also, Thanks for the wrapper. I have it implemented, but I'm still having issues. I can now print my fields, but can't make it write to a .csv.
Personally, I would have suggested not using the wrapper to start
with. At least not until you understand what it's giving you, which is
a dictionary.
I'm stuck on the csvf.writerow line at the bottom.
Am I reading this correctly, that it is doing a for loop passing in the column name to trim_col?
Basically, yes. But it's doing quite a bit more. It's creating a list
by doing a(n implicit) `for` loop and appending to the list on each
iteration.
When it writes, it produces the column headings, not the values.
I can't figure out how to pass the values
You need to understand Python dictionaries. They are pretty much the
bread-and-butter of the language.
A dictionary is a collection of (key, value) pairs. Iteration over a
dictionary is defined as iteration over the keys only. In other words,
for x in mydict:
pass
is equivalent to
for x in mydict.keys():
pass
This is a design decision that perhaps not everyone would have made,
but it was carefully considered and deemed a good balance between
readability and convenience for real-world use.
If you want to get the values, the most straightforward change to your
code is probably
csvf.writerow([trim_col(col) for col in row.values()])
But there are a number of other tips I'd like to share:
from csv import writer, QUOTE_NONNUMERIC
If you want Excel-compatible CSVs (that is, CSVs that are formed the
way that Excel writes them), then you shouldn't bother with any of the
configuration constants. QUOTE_NONNUMERIC is generally superfluous and
will make your CSVs slightly bigger (due to extra quotes that Excel
wouldn't have written). Excel is somewhat forgiving when reading CSVs,
so it shouldn't hurt to use the extra quotes when writing, but it's
unnecessary clutter at best.
query = "select uiiac, umsts, uiasd, count(umsts) as reccount from mslib.uact \
left outer join mslib.uast on umsts = uiasc \
group by uiiac, umsts, uiasd with rollup \
order by uiiac, umsts"
Continuing long lines with backslash is considered by most Python
programmers the least desirable way to handle long lines.
In the specific case of strings, it's definitely preferred to use
triple-quotes. You could, for example, write the above as
query = '''
select uiiac, umsts, uiasd, count(umsts) as reccount from mslib.uact
left outer join mslib.uast on umsts = uiasc
group by uiiac, umsts, uiasd with rollup
order by uiiac, umsts'''
Note that triple-quotes *do* include the newlines, whereas backslashes
do not. But for SQL statements (and HTML), extra whitespace of any
kind is semantically collapsed to a single space, so it doesn't
matter. If you needed to precisely control the whitespace in a string
literal yourself, you could use the implicit line continuation
afforded by parentheses, combined with the implicit concatenation of
adjacent string literals, like so:
query = (
'select uiiac, umsts, uiasd, count(umsts) as reccount from mslib.uact'
' left outer join mslib.uast on umsts = uiasc'
' group by uiiac, umsts, uiasd with rollup'
' order by uiiac, umsts')
Notice that if you do this, you need to have the separating whitespace
either at the end of each string fragment other than the last, or at
the beginning of each fragment other than the first. (I've done the
latter above.)
Also, as a style note, most Python programmers would not indent quite
like I've done in either of those examples (even though I would, and
actually do in my own code). Most of them would assume a monospaced
font, keep the `select` on the same line as `query`, and line up the
subsequent lines with the `select`. Also, many would put the closing
paren on the left edge, to line up with `query`.
# Strip trailing spaces as applicable
def trim_col(s):
return s.rstrip() if hasattr(s, 'rstrip') else s
This is a handy thing to use, and it's particularly helpful if you
have a lot of columns; but if you only need to trim a few columns, I
recommend doing it in SQL rather than in Python. (In general, the SQL
engine is fast and Python is slow, so it's preferable to give more of
the load to the SQL engine.)
with open('actbysts.csv', 'w', newline='') as file:
csvf = writer(file, quoting=QUOTE_NONNUMERIC)
for row in CursorByName(cur):
if row['UIIAC'] is not None and row['UMSTS'] is not None and row['UIASD'] is not None:
csvf.writerow([trim_col(col) for col in row])
When sharing Python code, it is especially important to watch the
indentation. As written, the above contains a syntax error, because
there is no body to the (explicit) `for` loop. I know that the code
you actually executed doesn't have this problem, because you got
*something* to write in your CSV, rather than a syntax error. But it
won't always be the case that an indentation error produces a syntax
error. Very often, it will simply indicate different semantics than
what you intended, but still be valid Python code.
Oh, and finally, it's best to avoid using the word "file" as a
variable name if you can help it, because that is the name of a
built-in function in Python. By convention, almost everyone simply
uses the letter `f` in cases like the code snippet above.
OK, I'm sure that's much longer than anyone wanted to read. Give
yourself a gold star if you've made it to the end.
John Y.
As an Amazon Associate we earn from qualifying purchases.