My code has a couple of "multiple assigments" and
somehow I think there should be a nicer way to do this in Python.
This is how it currently looks like:

# sum price fields  
              paf = paf + float(pa)
              pbf = pbf + float(pb)
              pcf = pcf + float(pc)
              pdf = pdf + float(pd)
              pef = pef + float(pe)
              pff = pff + float(pf)
              pgf = pgf + float(pg)
              phf = phf + float(ph)
# format to 2 decimals
    pas = "%.2f" % paf
    pbs = "%.2f" % pbf
    pcs = "%.2f" % pcf
    pds = "%.2f" % pdf
    pes = "%.2f" % pef
    pfs = "%.2f" % pff
    pgs = "%.2f" % pgf
    phs = "%.2f" % phf

Thanks in advance for improvemnet suggestions.

Dani AI

Generated

A concise cleanup that complements ’s list approach and avoids the common pitfalls seen in ’s “empty result” run: read the price file once into an in-memory lookup, accumulate column-wise with zip, and write rows with the csv module using context managers. The csv module and the file‑I/O tutorial show the recommended patterns (use with open(..., newline='') for csv files). (docs.python.org)

Example pattern (keeps the price table in memory, sums each price column, writes with csv.writer):

import csv

def load_prices(file, delim=','):
    with open(file, newline='') as fh:
        r = csv.reader(fh, delimiter=delim)
        return {row[0]: [float(x) if x else 0.0 for x in row[1:17:2]] for row in r}

prices = load_prices('test_it.csv', delim=';')  # choose ',' or ';' to match the file

with open('art-table.csv') as layout, open('prices_out.csv', 'w', newline='') as out:
    writer = csv.writer(out)
    for line in layout:
        parts = [p.strip() for p in line.split(',')]
        idx, codes = parts[0], parts[1:]
        lists = [prices.get(c, [0.0]*8) for c in codes]
        totals = [sum(col) for col in zip(*lists)]
        writer.writerow([idx] + ['{:.2f}'.format(x) for x in totals])

This keeps the inner loop cheap (lookup instead of re-reading the file), uses zip to do column-wise sums and csv.writer to produce safe CSV output. (docs.python.org)

Troubleshooting notes drawn from the thread: iterating for line in pline walks the characters of a string (not list elements) so the intended full line must be written at once or use csv.writer.writerow; outFile.close needs to be called (or better: use with so closing is automatic). If the input delimiter varies, csv.Sniffer().sniff() can detect it before parsing. (docs.python.org)

This keeps ’s list idea but removes repeated file opens and the small I/O/formatting traps that produced empty or partial output in ’s trial.

Recommended Answers

All 11 Replies

The solution is to use lists

loc = locals()
pf_list = [loc["p%sf" % x] + float(loc["p%s" % x]) for x in "abcdefgh"]
ps_list = ["%.2f" % val for val in pf_list]

or dicts

loc = locals()
pf_dict= dict((x, loc["p%sf" % x] + float(loc["p%s" % x])) for x in "abcdefgh")
ps_dict = dict((k, "%.2f" % v) for (k, v) in pf_dict.items()]
print(ps_dict["a"], ps_dict["b"])

Thanks, that's a lot better !
Now I'm preparing a comma separated file, I used to fill a line like this

 pline = ', '.join([indexfield, pas, pbs, pcs, pds, pes, pfs, pgs, phs])

How would I fill the lines using your lists solution ?

There are different options

pline = ', '.join([indexfield,] + ps_list)
# or
pline = ', '.join([indexfield,', '.join(ps_list)])
# or
from itertools import chain
pline = ', '.join(chain((indexfield,), ps_list))

Wow, that's great. Thanks a lot Gribouillis.

using lists I get empty result

using lists I get empty result

Post your code (running code if possible) with your issue.

This is the code that works:

#This code is working as of 2012-11-26 at 430PM
# sum some pricelist data of a csv file based upon record layout of
# a second csv file
# if artcode and rateband ok: 1 record
# for x artcodes per pricelist line sum prices

import csv
import time

arttable = 'art-table0.csv'     # de prijslijst-regel-tabel: regelid + x artcodes
fname = 'test_it.csv'          # de tabel met artikelcodes staffelpunten en -prijzen
outFile = open("prices0.csv", "w") # input voor generator: prijslijstregel + cum. staffelprijzen
new_staffel = []
usb_staffellist=['510205010050010005000']
kr_staffellist=['5010050010005000']
hdd_staffellist=['15102050100500']
art_list = []
for strLine in open(arttable):
    lstLine=strLine.strip('\n').split(',')
    indexfield=lstLine[0]
    paf = pbf = pcf = pdf = pef = pff = pgf = phf = 0
    for elem in lstLine[1:]:
          for item in open(fname):      
            lstData=item.strip('\n').split(',')
            andexfield=lstData[0]
            if andexfield == elem:
              pa = lstData[1]
              qa = lstData[2]
              pb = lstData[3]
              qb = lstData[4]
              pc = lstData[5]
              qc = lstData[6]
              pd = lstData[7]
              qd = lstData[8]
              pe = lstData[9]
              qe = lstData[10]
              pf = lstData[11]
              qf = lstData[12]
              pg = lstData[13]
              qg = lstData[14]
              ph = lstData[15]
              qh = lstData[16]

              new_staffel=[(qa + qb + qc + qd + qe + qf + qg + qh)]
              if new_staffel!=usb_staffellist:
                 print elem + ": Staffelpunten zijn NIET gelijk !!!"

              paf = paf + float(pa)
              pbf = pbf + float(pb)
              pcf = pcf + float(pc)
              pdf = pdf + float(pd)
              pef = pef + float(pe)
              pff = pff + float(pf)
              pgf = pgf + float(pg)
              phf = phf + float(ph)

    pas = "%.2f" % paf
    pbs = "%.2f" % pbf
    pcs = "%.2f" % pcf
    pds = "%.2f" % pdf
    pes = "%.2f" % pef
    pfs = "%.2f" % pff
    pgs = "%.2f" % pgf
    phs = "%.2f" % phf

    pline = ', '.join([indexfield, pas, pbs, pcs, pds, pes, pfs, pgs, phs])

    for line in pline:
        outFile.write(line)
    outFile.write('\n')
    outFile.close

Ouput:
USOR2GB, 7.26, 5.26, 4.26, 3.66, 3.26, 3.18, 3.01, 3.01
USOR4GB, 10.25, 9.23, 8.97, 8.71, 8.40, 8.36, 8.30, 3.01
USOR8GB, 10.25, 9.23, 8.97, 8.71, 8.40, 8.36, 8.30, 3.01
USOR16GB, 10.25, 9.23, 8.97, 8.71, 8.40, 8.36, 8.30, 3.01
USOR32GB, 10.25, 9.23, 8.97, 8.71, 8.40, 8.36, 8.30, 3.01
USOR64GB, 30.96, 28.96, 27.96, 27.36, 26.96, 26.34, 24.91, 3.01
USORFCDS, 4.25, 2.25, 1.25, 0.65, 0.45, 0.35, 0.30, 0.30
USORFCDI, 4.65, 2.60, 1.60, 1.00, 0.80, 0.70, 0.65, 0.30
USORLENS, 4.10, 2.10, 1.10, 0.50, 0.30, 0.20, 0.15, 0.15
USORDAST, 0.50, 0.50, 0.50, 0.50, 0.35, 0.25, 0.25, 0.15
USORDASU, 1.30, 1.30, 1.30, 1.30, 0.80, 0.45, 0.40, 0.15
USORACLY, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15
USORACKR, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15
USORACPS, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15
USORPAGB, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15
USORPAGC, 0.60, 0.60, 0.60, 0.60, 0.50, 0.50, 0.50, 0.15
USORPAGP, 4.85, 2.85, 1.85, 1.25, 0.95, 0.85, 0.80, 0.45
USORPAGF, 1.35, 1.35, 1.35, 1.35, 1.10, 1.10, 1.10, 0.15
USORPAFC, 9.95, 6.15, 3.75, 2.15, 1.55, 1.55, 1.55, 0.30
USORPAGG, 0.60, 0.60, 0.60, 0.60, 0.50, 0.50, 0.50, 0.15
USORPADP, 9.60, 5.55, 3.25, 1.90, 1.00, 1.00, 0.95, 0.30
USORPABL, 0.40, 0.40, 0.40, 0.40, 0.40, 0.40, 0.40, 0.15
USORPAPB, 0.10, 0.10, 0.10, 0.10, 0.05, 0.05, 0.05, 0.05
USORINGB, 0.60, 0.60, 0.60, 0.60, 0.50, 0.50, 0.50, 0.15
USORINBX, 0.40, 0.40, 0.40, 0.40, 0.40, 0.40, 0.40, 0.15
USORINBL, 2.84, 1.84, 1.08, 0.58, 0.50, 0.25, 0.18, 0.15

This is the new code that does not work as expected:

#This code is working as of 2012-11-26 at 430PM
# sum some pricelist data of a csv file based upon record layout of
# a second csv file

import csv
import time

arttable = 'art-table2.csv'     # de prijslijst-regel-tabel: regelid + x artcodes
fname = 'test_it.csv'          # de tabel met artikelcodes staffelpunten en -prijzen
outFile = open("prices2.csv", "w") # input voor generator: prijslijstregel + cum. staffelprijzen
new_staffel = []
lstLine = []
lstData = []
#ps_list= []
pf_list = []
usb_staffellist=['510205010050010005000']
kr_staffellist=['5010050010005000']
hdd_staffellist=['15102050100500']
art_list = []
for strLine in open(arttable):
    lstLine=strLine.strip('\n').split(',')
    indexfield=lstLine[0]
    paf = pbf = pcf = pdf = pef = pff = pgf = phf = 0
    for elem in lstLine[1:]:
          for item in open(fname):      
            lstData=item.strip('\n').split(';')
            andexfield=lstData[0]
            if andexfield == elem:   
              pa = lstData[1]
              qa = lstData[2]
              pb = lstData[3]
              qb = lstData[4]
              pc = lstData[5]
              qc = lstData[6]
              pd = lstData[7]
              qd = lstData[8]
              pe = lstData[9]
              qe = lstData[10]
              pf = lstData[11]
              qf = lstData[12]
              pg = lstData[13]
              qg = lstData[14]
              ph = lstData[15]
              qh = lstData[16]
              print pa, pb, pc, pd, pe, pf, pg, ph

              new_staffel=[(qa + qb + qc + qd + qe + qf + qg + qh)]
              if new_staffel!=usb_staffellist:
                 print elem + ": Staffelpunten zijn NIET gelijk !!!"

              loc = locals()
              pf_list = [loc["p%sf" % x] + float(loc["p%s" % x]) for x in "abcdefgh"]

    ps_list = ["%.2f" % val for val in pf_list]

    pline = ', '.join([indexfield,] + ps_list)

    for line in pline:
        outFile.write(line)
    outFile.write('\n')
    outFile.close

Ouput:

USOR2GB
USOR4GB
USOR8GB
USOR16GB
USOR32GB
USOR64GB
USORFCDS
USORFCDI
USORLENS
USORDAST
USORDASU
USORACLY
USORACKR
USORACPS
USORPAGB
USORPAGC
USORPAGP
USORPAGF
USORPAFC
USORPAGG
USORPADP
USORPABL
USORPAPB
USORINGB
USORINBX
USORINBL

These changes to your first code should work

#This code is working as of 2012-11-26 at 430PM
# sum some pricelist data of a csv file based upon record layout of
# a second csv file
# if artcode and rateband ok: 1 record
# for x artcodes per pricelist line sum prices

import csv
import time

arttable = 'art-table0.csv'     # de prijslijst-regel-tabel: regelid + x artcodes
fname = 'test_it.csv'          # de tabel met artikelcodes staffelpunten en -prijzen
outFile = open("prices0.csv", "w") # input voor generator: prijslijstregel + cum. staffelprijzen
new_staffel = []
usb_staffellist=['510205010050010005000']
kr_staffellist=['5010050010005000']
hdd_staffellist=['15102050100500']
art_list = []
for strLine in open(arttable):
    lstLine=strLine.strip('\n').split(',')
    indexfield=lstLine[0]
    PF = [0.0] * 8
    for elem in lstLine[1:]:
          for item in open(fname):      
            lstData=item.strip('\n').split(',')
            andexfield=lstData[0]
            if andexfield == elem:
                P = lsdata[1:17:2]
                Q = lsdata[2:17:2]
                new_staffel=[sum(Q)]
                if new_staffel!=usb_staffellist:
                    print elem + ": Staffelpunten zijn NIET gelijk !!!"

                PF = [(x + float(y)) for (x, y) in zip(PF, P)]

    PS = ["%.2f" % x for x in PF]

    pline = ', '.join([indexfield] + PS)

    for line in pline:
        outFile.write(line)
    outFile.write('\n')
    outFile.close

corrected lsdata to read as lstData but ran into another error:

  File "/home/dodonet/Documents/Scribus/kort4.py", line 27, in <module>
    new_staffel=[sum(Q)]
TypeError: unsupported operand type(s) for +: 'int' and 'str'

It means that Q contains other values than numbers. You can use

                new_staffel = [sum(float(x) for x in Q)]

for example. Try to understand what the code does and print lists until it works.

Yes, that's perfect !
Thanks a lot !

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.