You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
csv does not round-trip for complex numbers #98485
In this case, we don't have our data back, but at least it does not raise.
QUOTE_NONNUMERIC
Qouting docs:
No automatic data type conversion is performed unless the QUOTE_NONNUMERIC format option is specified (in which case unquoted fields are transformed into floats)
importcsvdata= [1, 1j]
withopen('example.csv', 'w') asf:
writer=csv.writer(f, quoting=csv.QUOTE_NONNUMERIC)
writer.writerow(data)
withopen('example.csv') asf:
contents=f.read()
print(contents) # 1,1jreader=csv.reader(contents, quoting=csv.QUOTE_NONNUMERIC)
print(list(reader))
# Traceback (most recent call last):# File "/Users/sobolev/Desktop/cpython/ex.py", line 11, in <module># print(list(reader))# ^^^^^^^^^^^^# ValueError: could not convert string to float: 'j'
In this case, it raises an error, while trying to convert 1j to float.
Current docs / tests
I cannot find any mentions of complex numbers in tests or docs for csv.
Solutions?
We can say that it works as expected: with this strange QUOTE_ALL formatting and QUOTE_NONNUMERIC exception. Add a test case for it and forget about it
We can try to quote complex as string: in this case it will be treated as "1j". I think it is much better, because it will allow users to convert this value to complex manually
Forbid writting complex numbers. However, I don't think it is a path we should go
Only addressing the first example, with quoting=csv.QUOTE_ALL or with default quoting, I do get the original data back as expected (on latest dev version):
with open('a.csv') as f:
reader = csv.reader(f, quoting=csv.QUOTE_ALL)
for r in reader:
print(r)
# ['1', '1j']
# ['2', '2j']
So with complex numbers you would need to complex(r[1]) when reading data.
If there was no way to get the original data back, of course it would be more alarming.
gh-155097 (PR #155099) adds a converter parameter to csv.reader which replaces the hard-coded float(). Since str(1j) is already written unquoted, complex numbers round-trip with:
The converter is called as converter(index, field), so converter=complex does not work — the index would be taken as the real part and the field as imag.
The QUOTE_ALL half of the report is unrelated and works as documented: in that mode the reader converts nothing, so every field is returned as a string.
Activity
pochmann commentedon Oct 20, 2022
I suggest you first fix your bug. Give
csv.readerthe file object, not the file contents as a string.pochmann commentedon Oct 20, 2022
Those two programs are identical. You're not using
QUOTE_NONNUMERIC.sobolevn commentedon Oct 20, 2022
@pochmann thanks!
It does not really matter. See:
This was a copy-paste error, updated.
akulakov commentedon Nov 9, 2022
Only addressing the first example, with
quoting=csv.QUOTE_ALLor with default quoting, I do get the original data back as expected (on latest dev version):So with complex numbers you would need to
complex(r[1])when reading data.If there was no way to get the original data back, of course it would be more alarming.
skirpichev commentedon Mar 25, 2025
@sobolevn, this doesn't work for floats as well. Or did I miss something?
serhiy-storchaka commentedon Aug 3, 2026
gh-155097 (PR #155099) adds a
converterparameter tocsv.readerwhich replaces the hard-codedfloat(). Sincestr(1j)is already written unquoted, complex numbers round-trip with:The converter is called as
converter(index, field), soconverter=complexdoes not work — the index would be taken as the real part and the field asimag.The
QUOTE_ALLhalf of the report is unrelated and works as documented: in that mode the reader converts nothing, so every field is returned as a string.