Die Verwendung des struct
Moduls der Python-Standardbibliothek wäre ziemlich einfach und extrem schnell, da es in C geschrieben ist.
Hier erfahren Sie, wie Sie damit tun können, was Sie wollen. Außerdem können Spalten mit Zeichen übersprungen werden, indem negative Werte für die Anzahl der Zeichen im Feld angegeben werden.
import struct
fieldwidths = (2, -10, 24)
fmtstring = ' '.join('{}{}'.format(abs(fw), 'x' if fw < 0 else 's')
for fw in fieldwidths)
fieldstruct = struct.Struct(fmtstring)
parse = fieldstruct.unpack_from
print('fmtstring: {!r}, recsize: {} chars'.format(fmtstring, fieldstruct.size))
line = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\n'
fields = parse(line)
print('fields: {}'.format(fields))
Ausgabe:
fmtstring: '2s 10x 24s', recsize: 36 chars
fields: ('AB', 'MNOPQRSTUVWXYZ0123456789')
Die folgenden Änderungen würden es in Python 2 oder 3 anpassen (und Unicode-Eingaben verarbeiten):
import struct
import sys
fieldstruct = struct.Struct(fmtstring)
if sys.version_info[0] < 3:
parse = fieldstruct.unpack_from
else:
unpack = fieldstruct.unpack_from
parse = lambda line: tuple(s.decode() for s in unpack(line.encode()))
Hier ist eine Möglichkeit, dies mit String-Slices zu tun, wie Sie überlegt haben, aber befürchtet haben, dass es zu hässlich werden könnte. Das Schöne daran ist, dass es nicht nur so hässlich ist, sondern auch in Python 2 und 3 unverändert funktioniert und Unicode-Strings verarbeiten kann. In Bezug auf die Geschwindigkeit ist es natürlich langsamer als die Versionen, die auf dem struct
Modul basieren , aber es könnte leicht beschleunigt werden, indem die Möglichkeit, Auffüllfelder zu haben, entfernt wird.
try:
from itertools import izip_longest
except ImportError:
from itertools import zip_longest as izip_longest
try:
from itertools import accumulate
except ImportError:
def accumulate(iterable):
'Return running totals (simplified version).'
total = next(iterable)
yield total
for value in iterable:
total += value
yield total
def make_parser(fieldwidths):
cuts = tuple(cut for cut in accumulate(abs(fw) for fw in fieldwidths))
pads = tuple(fw < 0 for fw in fieldwidths)
flds = tuple(izip_longest(pads, (0,)+cuts, cuts))[:-1]
parse = lambda line: tuple(line[i:j] for pad, i, j in flds if not pad)
parse.size = sum(abs(fw) for fw in fieldwidths)
parse.fmtstring = ' '.join('{}{}'.format(abs(fw), 'x' if fw < 0 else 's')
for fw in fieldwidths)
return parse
line = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\n'
fieldwidths = (2, -10, 24)
parse = make_parser(fieldwidths)
fields = parse(line)
print('format: {!r}, rec size: {} chars'.format(parse.fmtstring, parse.size))
print('fields: {}'.format(fields))
Ausgabe:
format: '2s 10x 24s', rec size: 36 chars
fields: ('AB', 'MNOPQRSTUVWXYZ0123456789')
struct.unpack
scheint mit Binärdaten zu arbeiten. Ich kann das nicht zum Laufen bringen.Ich bin mir nicht sicher, ob dies effizient ist, aber es sollte lesbar sein (im Gegensatz zum manuellen Schneiden). Ich habe eine Funktion definiert
slices
, die eine Zeichenfolge und Spaltenlängen abruft und die Teilzeichenfolgen zurückgibt. Ich habe es zu einem Generator gemacht, so dass für wirklich lange Zeilen keine temporäre Liste von Teilzeichenfolgen erstellt wird.def slices(s, *args): position = 0 for length in args: yield s[position:position + length] position += length
Beispiel
In [32]: list(slices('abcdefghijklmnopqrstuvwxyz0123456789', 2)) Out[32]: ['ab'] In [33]: list(slices('abcdefghijklmnopqrstuvwxyz0123456789', 2, 10, 50)) Out[33]: ['ab', 'cdefghijkl', 'mnopqrstuvwxyz0123456789'] In [51]: d,c,h = slices('dogcathouse', 3, 3, 5) In [52]: d,c,h Out[52]: ('dog', 'cat', 'house')
Aber ich denke, der Vorteil eines Generators geht verloren, wenn Sie alle Spalten gleichzeitig benötigen. Davon kann man profitieren, wenn Sie Spalten einzeln verarbeiten möchten, beispielsweise in einer Schleife.
quelle
struct
, aber sie ist lesbar und einfacher zu handhaben. Ich habe einige Tests mit Ihremslices function
,struct
Modul und auchre
Modul durchgeführt und es stellt sich für große Dateien heraus,struct
ist am schnellsten,re
kommt an zweiter Stelle (1,5x langsamer) und anslices
dritter Stelle (2x langsamer). Es ist jedoch ein geringer Overhead erforderlich,struct
sodass Sieslices function
bei kleineren Dateien schneller arbeiten können.Zwei weitere Optionen, die einfacher und schöner sind als die bereits erwähnten Lösungen:
Der erste ist die Verwendung von Pandas:
import pandas as pd path = 'filename.txt' # Using Pandas with a column specification col_specification = [(0, 20), (21, 30), (31, 50), (51, 100)] data = pd.read_fwf(path, colspecs=col_specification)
Und die zweite Option mit numpy.loadtxt:
import numpy as np # Using NumPy and letting it figure it out automagically data_also = np.loadtxt(path)
Es hängt wirklich davon ab, wie Sie Ihre Daten verwenden möchten.
quelle
colspecs='infer'
pandas.pydata.org/pandas-docs/stable/generated/…Der folgende Code enthält eine Skizze dessen, was Sie möglicherweise tun möchten, wenn Sie ernsthafte Dateibehandlungen mit fester Spaltenbreite durchführen müssen.
"Serious" = mehrere Datensatztypen in jedem von mehreren Dateitypen, Datensätze bis zu 1000 Byte, der Layout-Definierer und "gegnerische" Produzent / Verbraucher ist eine Regierungsabteilung mit Einstellung, Layoutänderungen führen zu nicht verwendeten Spalten, bis zu einer Million Datensätzen in einer Datei, ...
Features: Kompiliert die Strukturformate vor. Ignoriert unerwünschte Spalten. Konvertiert Eingabezeichenfolgen in erforderliche Datentypen (Skizze lässt Fehlerbehandlung aus). Konvertiert Datensätze in Objektinstanzen (oder Dikte oder benannte Tupel, wenn Sie dies bevorzugen).
Code:
import struct, datetime, io, pprint # functions for converting input fields to usable data cnv_text = rstrip cnv_int = int cnv_date_dmy = lambda s: datetime.datetime.strptime(s, "%d%m%Y") # ddmmyyyy # etc # field specs (field name, start pos (1-relative), len, converter func) fieldspecs = [ ('surname', 11, 20, cnv_text), ('given_names', 31, 20, cnv_text), ('birth_date', 51, 8, cnv_date_dmy), ('start_date', 71, 8, cnv_date_dmy), ] fieldspecs.sort(key=lambda x: x[1]) # just in case # build the format for struct.unpack unpack_len = 0 unpack_fmt = "" for fieldspec in fieldspecs: start = fieldspec[1] - 1 end = start + fieldspec[2] if start > unpack_len: unpack_fmt += str(start - unpack_len) + "x" unpack_fmt += str(end - start) + "s" unpack_len = end field_indices = range(len(fieldspecs)) print unpack_len, unpack_fmt unpacker = struct.Struct(unpack_fmt).unpack_from class Record(object): pass # or use named tuples raw_data = """\ ....v....1....v....2....v....3....v....4....v....5....v....6....v....7....v....8 Featherstonehaugh Algernon Marmaduke 31121969 01012005XX """ f = cStringIO.StringIO(raw_data) headings = f.next() for line in f: # The guts of this loop would of course be hidden away in a function/method # and could be made less ugly raw_fields = unpacker(line) r = Record() for x in field_indices: setattr(r, fieldspecs[x][0], fieldspecs[x][3](raw_fields[x])) pprint.pprint(r.__dict__) print "Customer name:", r.given_names, r.surname
Ausgabe:
78 10x20s20s8s12x8s {'birth_date': datetime.datetime(1969, 12, 31, 0, 0), 'given_names': 'Algernon Marmaduke', 'start_date': datetime.datetime(2005, 1, 1, 0, 0), 'surname': 'Featherstonehaugh'} Customer name: Algernon Marmaduke Featherstonehaugh
quelle
struct.error: unpack_from requires a buffer of at least 1157 bytes
> str = '1234567890' > w = [0,2,5,7,10] > [ str[ w[i-1] : w[i] ] for i in range(1,len(w)) ] ['12', '345', '67', '890']
quelle
Hier ist ein einfaches Modul für Python 3, basierend auf John Machins Antwort - passen Sie es nach Bedarf an :)
""" fixedwidth Parse and iterate through a fixedwidth text file, returning record objects. Adapted from https://stackoverflow.com/a/4916375/243392 USAGE import fixedwidth, pprint # define the fixed width fields we want # fieldspecs is a list of [name, description, start, width, type] arrays. fieldspecs = [ ["FILEID", "File Identification", 1, 6, "A/N"], ["STUSAB", "State/U.S. Abbreviation (USPS)", 7, 2, "A"], ["SUMLEV", "Summary Level", 9, 3, "A/N"], ["LOGRECNO", "Logical Record Number", 19, 7, "N"], ["POP100", "Population Count (100%)", 30, 9, "N"], ] # define the fieldtype conversion functions fieldtype_fns = { 'A': str.rstrip, 'A/N': str.rstrip, 'N': int, } # iterate over record objects in the file with open(f, 'rb'): for record in fixedwidth.reader(f, fieldspecs, fieldtype_fns): pprint.pprint(record.__dict__) # output: {'FILEID': 'SF1ST', 'LOGRECNO': 2, 'POP100': 1, 'STUSAB': 'TX', 'SUMLEV': '040'} {'FILEID': 'SF1ST', 'LOGRECNO': 3, 'POP100': 2, 'STUSAB': 'TX', 'SUMLEV': '040'} ... """ import struct, io # fieldspec columns iName, iDescription, iStart, iWidth, iType = range(5) def get_struct_unpacker(fieldspecs): """ Build the format string for struct.unpack to use, based on the fieldspecs. fieldspecs is a list of [name, description, start, width, type] arrays. Returns a string like "6s2s3s7x7s4x9s". """ unpack_len = 0 unpack_fmt = "" for fieldspec in fieldspecs: start = fieldspec[iStart] - 1 end = start + fieldspec[iWidth] if start > unpack_len: unpack_fmt += str(start - unpack_len) + "x" unpack_fmt += str(end - start) + "s" unpack_len = end struct_unpacker = struct.Struct(unpack_fmt).unpack_from return struct_unpacker class Record(object): pass # or use named tuples def reader(f, fieldspecs, fieldtype_fns): """ Wrap a fixedwidth file and return records according to the given fieldspecs. fieldspecs is a list of [name, description, start, width, type] arrays. fieldtype_fns is a dictionary of functions used to transform the raw string values, one for each type. """ # make sure fieldspecs are sorted properly fieldspecs.sort(key=lambda fieldspec: fieldspec[iStart]) struct_unpacker = get_struct_unpacker(fieldspecs) field_indices = range(len(fieldspecs)) for line in f: raw_fields = struct_unpacker(line) # split line into field values record = Record() for i in field_indices: fieldspec = fieldspecs[i] fieldname = fieldspec[iName] s = raw_fields[i].decode() # convert raw bytes to a string fn = fieldtype_fns[fieldspec[iType]] # get conversion function value = fn(s) # convert string to value (eg to an int) setattr(record, fieldname, value) yield record if __name__=='__main__': # test module import pprint, io # define the fields we want # fieldspecs are [name, description, start, width, type] fieldspecs = [ ["FILEID", "File Identification", 1, 6, "A/N"], ["STUSAB", "State/U.S. Abbreviation (USPS)", 7, 2, "A"], ["SUMLEV", "Summary Level", 9, 3, "A/N"], ["LOGRECNO", "Logical Record Number", 19, 7, "N"], ["POP100", "Population Count (100%)", 30, 9, "N"], ] # define a conversion function for integers def to_int(s): """ Convert a numeric string to an integer. Allows a leading ! as an indicator of missing or uncertain data. Returns None if no data. """ try: return int(s) except: try: return int(s[1:]) # ignore a leading ! except: return None # assume has a leading ! and no value # define the conversion fns fieldtype_fns = { 'A': str.rstrip, 'A/N': str.rstrip, 'N': to_int, # 'N': int, # 'D': lambda s: datetime.datetime.strptime(s, "%d%m%Y"), # ddmmyyyy # etc } # define a fixedwidth sample sample = """\ SF1ST TX04089000 00000023748 1 SF1ST TX04090000 00000033748! 2 SF1ST TX04091000 00000043748! """ sample_data = sample.encode() # convert string to bytes file_like = io.BytesIO(sample_data) # create a file-like wrapper around bytes # iterate over record objects in the file for record in reader(file_like, fieldspecs, fieldtype_fns): # print(record) pprint.pprint(record.__dict__)
quelle
So habe ich es mit einem Wörterbuch gelöst, das enthält, wo Felder beginnen und enden. Durch die Angabe von Start- und Endpunkten konnte ich auch Änderungen in der Länge der Spalte verwalten.
# fixed length # '---------- ------- ----------- -----------' line = '20.06.2019 myname active mydevice ' SLICES = {'date_start': 0, 'date_end': 10, 'name_start': 11, 'name_end': 18, 'status_start': 19, 'status_end': 30, 'device_start': 31, 'device_end': 42} def get_values_as_dict(line, SLICES): values = {} key_list = {key.split("_")[0] for key in SLICES.keys()} for key in key_list: values[key] = line[SLICES[key+"_start"]:SLICES[key+"_end"]].strip() return values >>> print (get_values_as_dict(line,SLICES)) {'status': 'active', 'name': 'myname', 'date': '20.06.2019', 'device': 'mydevice'}
quelle
Hier ist, was NumPy unter der Haube verwendet (viel vereinfacht, aber dennoch - dieser Code befindet sich im
LineSplitter class
Inneren der_iotools module
):import numpy as np DELIMITER = (20, 10, 10, 20, 10, 10, 20) idx = np.cumsum([0] + list(DELIMITER)) slices = [slice(i, j) for (i, j) in zip(idx[:-1], idx[1:])] def parse(line): return [line[s] for s in slices]
Es werden keine negativen Trennzeichen zum Ignorieren von Spalten verarbeitet, daher ist es nicht so vielseitig wie
struct
, aber es ist schneller.quelle
Das Schneiden von Saiten muss nicht hässlich sein, solange Sie es organisiert halten. Speichern Sie Ihre Feldbreiten in einem Wörterbuch und verwenden Sie dann die zugehörigen Namen, um ein Objekt zu erstellen:
from collections import OrderedDict class Entry: def __init__(self, line): name2width = OrderedDict() name2width['foo'] = 2 name2width['bar'] = 3 name2width['baz'] = 2 pos = 0 for name, width in name2width.items(): val = line[pos : pos + width] if len(val) != width: raise ValueError("not enough characters: \'{}\'".format(line)) setattr(self, name, val) pos += width file = "ab789yz\ncd987wx\nef555uv" entry = [] for line in file.split('\n'): entry.append(Entry(line)) print(entry[1].bar) # output: 987
quelle
Da meine alte Arbeit häufig 1 Million Zeilen mit Daten mit fester Breite verarbeitet, habe ich dieses Problem untersucht, als ich anfing, Python zu verwenden.
Es gibt 2 Arten von FixedWidth
Wenn die Ressourcenzeichenfolge ausschließlich aus ASCII-Zeichen besteht, ist ASCII FixedWidth = Unicode FixedWidth
Glücklicherweise unterscheiden sich String und Byte in py3, was die Verwirrung beim Umgang mit Doppelbyte-codierten Zeichen (Eggbk, Big5, Euc-JP, Shift-JIS usw.) verringert.
Für die Verarbeitung von "ASCII FixedWidth" wird der String normalerweise in Bytes konvertiert und dann aufgeteilt.
Ohne den Import von Modulen von
Drittanbietern totalLineCount = 1 Million, lineLength = 800 Byte, FixedWidthArgs = (10,25,4, ....) habe ich die Zeile auf ungefähr 5 Arten aufgeteilt und komme zu folgendem Ergebnis:
slice(bytes)
ist schneller alsslice(string)
Beim Umgang mit großen Dateien verwenden wir häufig
with open ( file, "rb") as f:
.Die Methode durchläuft eine der oben genannten Dateien, ungefähr 2,4 Sekunden.
Ich denke, der entsprechende Handler, der 1 Million Datenzeilen verarbeitet, teilt jede Zeile in 20 Felder auf und benötigt weniger als 2,4 Sekunden.
Ich finde das nur
stuct
unditemgetter
erfülle die Anforderungenps: Für die normale Anzeige habe ich Unicode str in Bytes konvertiert. Wenn Sie sich in einer Doppelbyte-Umgebung befinden, müssen Sie dies nicht tun.
from itertools import accumulate from operator import itemgetter def oprt_parser(sArgs): sum_arg = tuple(accumulate(abs(i) for i in sArgs)) # Negative parameter field index cuts = tuple(i for i,num in enumerate(sArgs) if num < 0) # Get slice args and Ignore fields of negative length ig_Args = tuple(item for i, item in enumerate(zip((0,)+sum_arg,sum_arg)) if i not in cuts) # Generate `operator.itemgetter` object oprtObj =itemgetter(*[slice(s,e) for s,e in ig_Args]) return oprtObj lineb = b'abcdefghijklmnopqrstuvwxyz\xb0\xa1\xb2\xbb\xb4\xd3\xb5\xc4\xb6\xee\xb7\xa2\xb8\xf6\xba\xcd0123456789' line = lineb.decode("GBK") # Unicode Fixed Width fieldwidthsU = (13, -13, 4, -4, 5,-5) # Negative width fields is ignored # ASCII Fixed Width fieldwidths = (13, -13, 8, -8, 5,-5) # Negative width fields is ignored # Unicode FixedWidth processing parse = oprt_parser(fieldwidthsU) fields = parse(line) print('Unicode FixedWidth','fields: {}'.format(tuple(map(lambda s: s.encode("GBK"), fields)))) # ASCII FixedWidth processing parse = oprt_parser(fieldwidths) fields = parse(lineb) print('ASCII FixedWidth','fields: {}'.format(fields)) line = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\n' fieldwidths = (2, -10, 24) parse = oprt_parser(fieldwidths) fields = parse(line) print(f"fields: {fields}")
Ausgabe:
Unicode FixedWidth fields: (b'abcdefghijklm', b'\xb0\xa1\xb2\xbb\xb4\xd3\xb5\xc4', b'01234') ASCII FixedWidth fields: (b'abcdefghijklm', b'\xb0\xa1\xb2\xbb\xb4\xd3\xb5\xc4', b'01234') fields: ('AB', 'MNOPQRSTUVWXYZ0123456789')
oprt_parser
ist 4xmake_parser
(Listenverständnis + Slice)Während der Forschung wurde festgestellt, dass die Effizienz der
re
Methode schneller zunimmt , wenn die CPU-Geschwindigkeit schneller ist.Da ich nicht mehr und bessere Computer zum Testen habe, geben Sie meinen Testcode an. Wenn jemand interessiert ist, können Sie ihn mit einem schnelleren Computer testen.
Run Environment:
import timeit import time import re from itertools import accumulate from operator import itemgetter def eff2(stmt,onlyNum= False,showResult=False): '''test function''' if onlyNum: rl = timeit.repeat(stmt=stmt,repeat=roundI,number=timesI,globals=globals()) avg = sum(rl) / len(rl) return f"{avg * (10 ** 6)/timesI:0.4f}" else: rl = timeit.repeat(stmt=stmt,repeat=10,number=1000,globals=globals()) avg = sum(rl) / len(rl) print(f"【{stmt}】") print(f"\tquick avg = {avg * (10 ** 6)/1000:0.4f} s/million") if showResult: print(f"\t Result = {eval(stmt)}\n\t timelist = {rl}\n") else: print("") def upDouble(argList,argRate): return [c*argRate for c in argList] tbStr = "000000001111000002222真2233333333000000004444444QAZ55555555000000006666666ABC这些事中文字abcdefghijk" tbBytes = tbStr.encode("GBK") a20 = (4,4,2,2,2,3,2,2, 2 ,2,8,8,7,3,8,8,7,3, 12 ,11) a20U = (4,4,2,2,2,3,2,2, 1 ,2,8,8,7,3,8,8,7,3, 6 ,11) Slng = 800 rateS = Slng // 100 tStr = "".join(upDouble(tbStr , rateS)) tBytes = tStr.encode("GBK") spltArgs = upDouble( a20 , rateS) spltArgsU = upDouble( a20U , rateS) testList = [] timesI = 100000 roundI = 5 print(f"test round = {roundI} timesI = {timesI} sourceLng = {len(tStr)} argFieldCount = {len(spltArgs)}") print(f"pure str \n{''.ljust(60,'-')}") # ========================================== def str_parser(sArgs): def prsr(oStr): r = [] r_ap = r.append stt=0 for lng in sArgs: end = stt + lng r_ap(oStr[stt:end]) stt = end return tuple(r) return prsr Str_P = str_parser(spltArgsU) # eff2("Str_P(tStr)") testList.append("Str_P(tStr)") print(f"pure bytes \n{''.ljust(60,'-')}") # ========================================== def byte_parser(sArgs): def prsr(oBytes): r, stt = [], 0 r_ap = r.append for lng in sArgs: end = stt + lng r_ap(oBytes[stt:end]) stt = end return r return prsr Byte_P = byte_parser(spltArgs) # eff2("Byte_P(tBytes)") testList.append("Byte_P(tBytes)") # re,bytes print(f"re compile object \n{''.ljust(60,'-')}") # ========================================== def rebc_parser(sArgs,otype="b"): re_Args = "".join([f"(.{{{n}}})" for n in sArgs]) if otype == "b": rebc_Args = re.compile(re_Args.encode("GBK")) else: rebc_Args = re.compile(re_Args) def prsr(oBS): return rebc_Args.match(oBS).groups() return prsr Rebc_P = rebc_parser(spltArgs) # eff2("Rebc_P(tBytes)") testList.append("Rebc_P(tBytes)") Rebc_Ps = rebc_parser(spltArgsU,"s") # eff2("Rebc_Ps(tStr)") testList.append("Rebc_Ps(tStr)") print(f"struct \n{''.ljust(60,'-')}") # ========================================== import struct def struct_parser(sArgs): struct_Args = " ".join(map(lambda x: str(x) + "s", sArgs)) def prsr(oBytes): return struct.unpack(struct_Args, oBytes) return prsr Struct_P = struct_parser(spltArgs) # eff2("Struct_P(tBytes)") testList.append("Struct_P(tBytes)") print(f"List Comprehensions + slice \n{''.ljust(60,'-')}") # ========================================== import itertools def slice_parser(sArgs): tl = tuple(itertools.accumulate(sArgs)) slice_Args = tuple(zip((0,)+tl,tl)) def prsr(oBytes): return [oBytes[s:e] for s, e in slice_Args] return prsr Slice_P = slice_parser(spltArgs) # eff2("Slice_P(tBytes)") testList.append("Slice_P(tBytes)") def sliceObj_parser(sArgs): tl = tuple(itertools.accumulate(sArgs)) tl2 = tuple(zip((0,)+tl,tl)) sliceObj_Args = tuple(slice(s,e) for s,e in tl2) def prsr(oBytes): return [oBytes[so] for so in sliceObj_Args] return prsr SliceObj_P = sliceObj_parser(spltArgs) # eff2("SliceObj_P(tBytes)") testList.append("SliceObj_P(tBytes)") SliceObj_Ps = sliceObj_parser(spltArgsU) # eff2("SliceObj_Ps(tStr)") testList.append("SliceObj_Ps(tStr)") print(f"operator.itemgetter + slice object \n{''.ljust(60,'-')}") # ========================================== def oprt_parser(sArgs): sum_arg = tuple(accumulate(abs(i) for i in sArgs)) cuts = tuple(i for i,num in enumerate(sArgs) if num < 0) ig_Args = tuple(item for i,item in enumerate(zip((0,)+sum_arg,sum_arg)) if i not in cuts) oprtObj =itemgetter(*[slice(s,e) for s,e in ig_Args]) return oprtObj Oprt_P = oprt_parser(spltArgs) # eff2("Oprt_P(tBytes)") testList.append("Oprt_P(tBytes)") Oprt_Ps = oprt_parser(spltArgsU) # eff2("Oprt_Ps(tStr)") testList.append("Oprt_Ps(tStr)") print("|".join([s.split("(")[0].center(11," ") for s in testList])) print("|".join(["".center(11,"-") for s in testList])) print("|".join([eff2(s,True).rjust(11," ") for s in testList]))
Ausgabe:
Test round = 5 timesI = 100000 sourceLng = 744 argFieldCount = 20 ... ... Str_P | Byte_P | Rebc_P | Rebc_Ps | Struct_P | Slice_P | SliceObj_P|SliceObj_Ps| Oprt_P | Oprt_Ps -----------|-----------|-----------|-----------|-- ---------|-----------|-----------|-----------|---- -------|----------- 9.6315| 7.5952| 4.4187| 5.6867| 1.5123| 5.2915| 4.2673| 5.7121| 2.4713| 3.9051
quelle