0

i am trying to write string to csv file that i opened in 'wb' mode. i get the above error despite i provided to csv writer a byte object i used pdb to make sure that i am right

(Pdb) type(row.encode("utf-8"))
<class 'bytes'>

i know that i can open it only in 'w' mode but it should be compatible with python2.7 and in python 2.7 it insert redundant empty lines if i opens the files with 'w'. in addition that should be compatible i want to understand what i am doing wrong here.

rows_list=[]
rows_list.append('plimit')
rows_list.append('#i_pstate')
csvfile=open(output_file_path, 'wb')    
try:
    filewriter = csv.writer(csvfile, delimiter=',',
                                quotechar='|', quoting=csv.QUOTE_MINIMAL)
    #import pdb;pdb.set_trace()
    for row in rows_list:
        filewriter.writerow([row.encode("utf-8")])
except Exception as ex:
    print ("error occurred '%s'"% (ex))  
    return -1
finally:
   csvfile.close()    

full traceback:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "c:\pythonsv\icelake\debug\domains\ice\platform_config_generation.py", line 81, in write_max_pstate_config_csv
    filewriter.writerow([row.encode("utf-8")])
TypeError: a bytes-like object is required, not 's
Yonatan Amir
  • 85
  • 1
  • 11
  • https://stackoverflow.com/questions/34283178/typeerror-a-bytes-like-object-is-required-not-str-in-python-and-csv – user202729 Aug 15 '19 at 13:02
  • 2
    Can you please remove the `try`/`except` and just let any exception happen instead of catching and printing it? Then show the stack trace so that we can see where the error originates. – mkrieger1 Aug 15 '19 at 13:13
  • What is `rows_list`? I would assume a list of strings, but could you confirm? Posting part of it would help. See [mre] for more pointers. – wjandrea Aug 15 '19 at 13:45
  • @mkrieger1 Traceback (most recent call last): File "", line 1, in File "c:\pythonsv\icelake\debug\domains\ice\platform_config_generation.py", line 81, in write_max_pstate_config_csv filewriter.writerow([row.encode("utf-8")]) TypeError: a bytes-like object is required, not 'str' – Yonatan Amir Aug 15 '19 at 14:16
  • @wjandrea you are right rows_list it is just list of strings rows_list=[] rows_list.append('plimit') rows_list.append('#i_pstate') – Yonatan Amir Aug 15 '19 at 14:18
  • @Yonatan Please [edit] the question. Comments are not great for posting code. – wjandrea Aug 15 '19 at 14:33
  • I don't think you're going to enjoy writing a Python 2/3 compatible program using the `csv` module, since that module has changed significantly. It didn't accept `unicode` input in Python 2, but does now (Py3's `str` is Py2's `unicode`). – lenz Aug 15 '19 at 14:44

2 Answers2

2

The biggest difference between Python 2 and Python 3 is the way they handle text. In Python 3 strings are thought as sequence of characters, and in Python 2 they are thought as sequence of Bytes, with the "unicode" object to be used to work with sequence of characters.

Although late work in Python 2 could proper work with text as text, by using unicode, and even by default with a from __future__ import unicode_literals in the beggining of the file, the csv module was specially difficult to handle - it won't work well with "real text" in Python 2, and you've just hit those difficulties.

So, if your program have to work with both Python 2 and Python 3, and use CSV in both, I think the best way is to have some state variables, and run slightly differing code-paths for each language.

Basically, work with all data inside your program as unicode (plain Python 3 strings, and you may resort to the from __future__ unicode_literals to write the same .py file.

from __future__ import unicode_literals

if sys.version_info.major < 3:
    file_mode = "wb"
    prepare_text = lambda t: t.encode("utf-8")
else:
    file_mode = "wt"
    prepare_text = lambda t: t

rows_list=[]
rows_list.append('plimit')
rows_list.append('#i_pstate')
csvfile=open(output_file_path, file_mode)    

try:
    filewriter = csv.writer(csvfile, delimiter=prepare_text(','),
                            quotechar=prepare_text('|'), quoting=csv.QUOTE_MINIMAL)
    for row in rows_list:
        filewriter.writerow(prepare_text(field) for field in row)
except Exception as ex:
    print ("error occurred '%s'"% (ex))  
    return -1
finally:
   csvfile.close()  
jsbueno
  • 99,910
  • 10
  • 151
  • 209
0

i finally used if else statement on the open function and it was enough

import six
if not six.PY2:#python3
        csvfile=open(output_file_path, 'w',newline='')
    else:#python2    
        csvfile=open(output_file_path, 'wb')
Yonatan Amir
  • 85
  • 1
  • 11