This action will force synchronization from OpenHarmony-SIG/python, which will overwrite any changes that you have made since you forked the repository, and can not be recovered!!!
Synchronous operation will process in the background and will refresh the page when finishing processing. Please be patient.
"""csv.py - read/write/investigate CSV files"""import refrom _csv import Error, __version__, writer, reader, register_dialect, \unregister_dialect, get_dialect, list_dialects, \field_size_limit, \QUOTE_MINIMAL, QUOTE_ALL, QUOTE_NONNUMERIC, QUOTE_NONE, \__doc__from _csv import Dialect as _Dialectfrom io import StringIO__all__ = ["QUOTE_MINIMAL", "QUOTE_ALL", "QUOTE_NONNUMERIC", "QUOTE_NONE","Error", "Dialect", "__doc__", "excel", "excel_tab","field_size_limit", "reader", "writer","register_dialect", "get_dialect", "list_dialects", "Sniffer","unregister_dialect", "__version__", "DictReader", "DictWriter","unix_dialect"]class Dialect:"""Describe a CSV dialect.This must be subclassed (see csv.excel). Valid attributes are:delimiter, quotechar, escapechar, doublequote, skipinitialspace,lineterminator, quoting."""_name = ""_valid = False# placeholdersdelimiter = Nonequotechar = Noneescapechar = Nonedoublequote = Noneskipinitialspace = Nonelineterminator = Nonequoting = Nonedef __init__(self):if self.__class__ != Dialect:self._valid = Trueself._validate()def _validate(self):try:_Dialect(self)except TypeError as e:# We do this for compatibility with py2.3raise Error(str(e))class excel(Dialect):"""Describe the usual properties of Excel-generated CSV files."""delimiter = ','quotechar = '"'doublequote = Trueskipinitialspace = Falselineterminator = '\r\n'quoting = QUOTE_MINIMALregister_dialect("excel", excel)class excel_tab(excel):"""Describe the usual properties of Excel-generated TAB-delimited files."""delimiter = '\t'register_dialect("excel-tab", excel_tab)class unix_dialect(Dialect):"""Describe the usual properties of Unix-generated CSV files."""delimiter = ','quotechar = '"'doublequote = Trueskipinitialspace = Falselineterminator = '\n'quoting = QUOTE_ALLregister_dialect("unix", unix_dialect)class DictReader:def __init__(self, f, fieldnames=None, restkey=None, restval=None,dialect="excel", *args, **kwds):self._fieldnames = fieldnames # list of keys for the dictself.restkey = restkey # key to catch long rowsself.restval = restval # default value for short rowsself.reader = reader(f, dialect, *args, **kwds)self.dialect = dialectself.line_num = 0def __iter__(self):return self@propertydef fieldnames(self):if self._fieldnames is None:try:self._fieldnames = next(self.reader)except StopIteration:passself.line_num = self.reader.line_numreturn self._fieldnames@fieldnames.setterdef fieldnames(self, value):self._fieldnames = valuedef __next__(self):if self.line_num == 0:# Used only for its side effect.self.fieldnamesrow = next(self.reader)self.line_num = self.reader.line_num# unlike the basic reader, we prefer not to return blanks,# because we will typically wind up with a dict full of None# valueswhile row == []:row = next(self.reader)d = dict(zip(self.fieldnames, row))lf = len(self.fieldnames)lr = len(row)if lf < lr:d[self.restkey] = row[lf:]elif lf > lr:for key in self.fieldnames[lr:]:d[key] = self.restvalreturn dclass DictWriter:def __init__(self, f, fieldnames, restval="", extrasaction="raise",dialect="excel", *args, **kwds):self.fieldnames = fieldnames # list of keys for the dictself.restval = restval # for writing short dictsif extrasaction.lower() not in ("raise", "ignore"):raise ValueError("extrasaction (%s) must be 'raise' or 'ignore'"% extrasaction)self.extrasaction = extrasactionself.writer = writer(f, dialect, *args, **kwds)def writeheader(self):header = dict(zip(self.fieldnames, self.fieldnames))return self.writerow(header)def _dict_to_list(self, rowdict):if self.extrasaction == "raise":wrong_fields = rowdict.keys() - self.fieldnamesif wrong_fields:raise ValueError("dict contains fields not in fieldnames: "+ ", ".join([repr(x) for x in wrong_fields]))return (rowdict.get(key, self.restval) for key in self.fieldnames)def writerow(self, rowdict):return self.writer.writerow(self._dict_to_list(rowdict))def writerows(self, rowdicts):return self.writer.writerows(map(self._dict_to_list, rowdicts))# Guard Sniffer's type checking against builds that exclude complex()try:complexexcept NameError:complex = floatclass Sniffer:'''"Sniffs" the format of a CSV file (i.e. delimiter, quotechar)Returns a Dialect object.'''def __init__(self):# in case there is more than one possible delimiterself.preferred = [',', '\t', ';', ' ', ':']def sniff(self, sample, delimiters=None):"""Returns a dialect (or None) corresponding to the sample"""quotechar, doublequote, delimiter, skipinitialspace = \self._guess_quote_and_delimiter(sample, delimiters)if not delimiter:delimiter, skipinitialspace = self._guess_delimiter(sample,delimiters)if not delimiter:raise Error("Could not determine delimiter")class dialect(Dialect):_name = "sniffed"lineterminator = '\r\n'quoting = QUOTE_MINIMAL# escapechar = ''dialect.doublequote = doublequotedialect.delimiter = delimiter# _csv.reader won't accept a quotechar of ''dialect.quotechar = quotechar or '"'dialect.skipinitialspace = skipinitialspacereturn dialectdef _guess_quote_and_delimiter(self, data, delimiters):"""Looks for text enclosed between two identical quotes(the probable quotechar) which are preceded and followedby the same character (the probable delimiter).For example:,'some text',The quote with the most wins, same with the delimiter.If there is no quotechar the delimiter can't be determinedthis way."""matches = []for restr in (r'(?P<delim>[^\w\n"\'])(?P<space> ?)(?P<quote>["\']).*?(?P=quote)(?P=delim)', # ,".*?",r'(?:^|\n)(?P<quote>["\']).*?(?P=quote)(?P<delim>[^\w\n"\'])(?P<space> ?)', # ".*?",r'(?P<delim>[^\w\n"\'])(?P<space> ?)(?P<quote>["\']).*?(?P=quote)(?:$|\n)', # ,".*?"r'(?:^|\n)(?P<quote>["\']).*?(?P=quote)(?:$|\n)'): # ".*?" (no delim, no space)regexp = re.compile(restr, re.DOTALL | re.MULTILINE)matches = regexp.findall(data)if matches:breakif not matches:# (quotechar, doublequote, delimiter, skipinitialspace)return ('', False, None, 0)quotes = {}delims = {}spaces = 0groupindex = regexp.groupindexfor m in matches:n = groupindex['quote'] - 1key = m[n]if key:quotes[key] = quotes.get(key, 0) + 1try:n = groupindex['delim'] - 1key = m[n]except KeyError:continueif key and (delimiters is None or key in delimiters):delims[key] = delims.get(key, 0) + 1try:n = groupindex['space'] - 1except KeyError:continueif m[n]:spaces += 1quotechar = max(quotes, key=quotes.get)if delims:delim = max(delims, key=delims.get)skipinitialspace = delims[delim] == spacesif delim == '\n': # most likely a file with a single columndelim = ''else:# there is *no* delimiter, it's a single column of quoted datadelim = ''skipinitialspace = 0# if we see an extra quote between delimiters, we've got a# double quoted formatdq_regexp = re.compile(r"((%(delim)s)|^)\W*%(quote)s[^%(delim)s\n]*%(quote)s[^%(delim)s\n]*%(quote)s\W*((%(delim)s)|$)" % \{'delim':re.escape(delim), 'quote':quotechar}, re.MULTILINE)if dq_regexp.search(data):doublequote = Trueelse:doublequote = Falsereturn (quotechar, doublequote, delim, skipinitialspace)def _guess_delimiter(self, data, delimiters):"""The delimiter /should/ occur the same number of times oneach row. However, due to malformed data, it may not. We don't wantan all or nothing approach, so we allow for small variations in thisnumber.1) build a table of the frequency of each character on every line.2) build a table of frequencies of this frequency (meta-frequency?),e.g. 'x occurred 5 times in 10 rows, 6 times in 1000 rows,7 times in 2 rows'3) use the mode of the meta-frequency to determine the /expected/frequency for that character4) find out how often the character actually meets that goal5) the character that best meets its goal is the delimiterFor performance reasons, the data is evaluated in chunks, so it cantry and evaluate the smallest portion of the data possible, evaluatingadditional chunks as necessary."""data = list(filter(None, data.split('\n')))ascii = [chr(c) for c in range(127)] # 7-bit ASCII# build frequency tableschunkLength = min(10, len(data))iteration = 0charFrequency = {}modes = {}delims = {}start, end = 0, chunkLengthwhile start < len(data):iteration += 1for line in data[start:end]:for char in ascii:metaFrequency = charFrequency.get(char, {})# must count even if frequency is 0freq = line.count(char)# value is the modemetaFrequency[freq] = metaFrequency.get(freq, 0) + 1charFrequency[char] = metaFrequencyfor char in charFrequency.keys():items = list(charFrequency[char].items())if len(items) == 1 and items[0][0] == 0:continue# get the mode of the frequenciesif len(items) > 1:modes[char] = max(items, key=lambda x: x[1])# adjust the mode - subtract the sum of all# other frequenciesitems.remove(modes[char])modes[char] = (modes[char][0], modes[char][1]- sum(item[1] for item in items))else:modes[char] = items[0]# build a list of possible delimitersmodeList = modes.items()total = float(min(chunkLength * iteration, len(data)))# (rows of consistent data) / (number of rows) = 100%consistency = 1.0# minimum consistency thresholdthreshold = 0.9while len(delims) == 0 and consistency >= threshold:for k, v in modeList:if v[0] > 0 and v[1] > 0:if ((v[1]/total) >= consistency and(delimiters is None or k in delimiters)):delims[k] = vconsistency -= 0.01if len(delims) == 1:delim = list(delims.keys())[0]skipinitialspace = (data[0].count(delim) ==data[0].count("%c " % delim))return (delim, skipinitialspace)# analyze another chunkLength linesstart = endend += chunkLengthif not delims:return ('', 0)# if there's more than one, fall back to a 'preferred' listif len(delims) > 1:for d in self.preferred:if d in delims.keys():skipinitialspace = (data[0].count(d) ==data[0].count("%c " % d))return (d, skipinitialspace)# nothing else indicates a preference, pick the character that# dominates(?)items = [(v,k) for (k,v) in delims.items()]items.sort()delim = items[-1][1]skipinitialspace = (data[0].count(delim) ==data[0].count("%c " % delim))return (delim, skipinitialspace)def has_header(self, sample):# Creates a dictionary of types of data in each column. If any# column is of a single type (say, integers), *except* for the first# row, then the first row is presumed to be labels. If the type# can't be determined, it is assumed to be a string in which case# the length of the string is the determining factor: if all of the# rows except for the first are the same length, it's a header.# Finally, a 'vote' is taken at the end for each column, adding or# subtracting from the likelihood of the first row being a header.rdr = reader(StringIO(sample), self.sniff(sample))header = next(rdr) # assume first row is headercolumns = len(header)columnTypes = {}for i in range(columns): columnTypes[i] = Nonechecked = 0for row in rdr:# arbitrary number of rows to check, to keep it saneif checked > 20:breakchecked += 1if len(row) != columns:continue # skip rows that have irregular number of columnsfor col in list(columnTypes.keys()):for thisType in [int, float, complex]:try:thisType(row[col])breakexcept (ValueError, OverflowError):passelse:# fallback to length of stringthisType = len(row[col])if thisType != columnTypes[col]:if columnTypes[col] is None: # add new column typecolumnTypes[col] = thisTypeelse:# type is inconsistent, remove column from# considerationdel columnTypes[col]# finally, compare results against first row and "vote"# on whether it's a headerhasHeader = 0for col, colType in columnTypes.items():if type(colType) == type(0): # it's a lengthif len(header[col]) != colType:hasHeader += 1else:hasHeader -= 1else: # attempt typecasttry:colType(header[col])except (ValueError, TypeError):hasHeader += 1else:hasHeader -= 1return hasHeader > 0
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。