1

I am trying to write a code that takes in a csv, runs a ping on the value in the first column and then outputs the status to the second column. Everything in the code runs fine until it tries to write out to the csv at which time I get this error
line 35, in writer.writerows(columns) TypeError: 'str' does not support the buffer interface

import os
import csv
from collections import defaultdict
i = 0
#read file
columns = defaultdict(list)

with open('hosts.csv') as f:
    reader = csv.DictReader(f)
    for row in reader:
        for (k,v) in row.items():
            columns[k].append(v)
f.close()
print('[DEBUG]', columns['host'])
print('[DEBUG] 1st host is', (columns['host'])[0])
print('[DEBUG]', columns['status'])

#ping hosts
hostname = (columns['host'])[i]
response = os.system("ping -n 1 " + hostname)
print ("[DEBUG]", response)
if response == 0:
    print (hostname, 'is up')
    (columns['status'])[i] = 'Up'
    i = i+1
else:
    print (hostname, 'is down')
    (columns['status'])[i] = 'Down'
    i = i+1

#write results
with open("hosts.csv", "wb") as f:
    writer =csv.writer(f)
    print("[DEBUG] just before write rows")
    writer.writerows(columns)
    print("[DEBUG] after write rows")
f.close()

The csv contains the following

host,status,name
8.8.8.8,down,google.com

and should return

host,status,name
8.8.8.8,Up,google.com

I am using Python 3.4

  • possible duplicate of [TypeError: 'str' does not support the buffer interface](http://stackoverflow.com/questions/5471158/typeerror-str-does-not-support-the-buffer-interface) – Nir Alfasi Jul 21 '14 at 04:40

1 Answers1

0

You are reading the CSV in one format and writing in another one, where columns is defaultdict with list of values inside a dict.

Here's a better way to solve this problem, maintaing the original file structure:

import os
import csv

with open('hosts.csv') as f:
    reader = csv.DictReader(f)
    rows = list(reader)

hosts = [row['host'] for row in rows]
statuses = [row['status'] for row in rows]

print('[DEBUG]', hosts)
print('[DEBUG] 1st host is', hosts[0])
print('[DEBUG]', statuses)

for row in rows:
    #ping hosts
    hostname = row['host']
    response = os.system("ping -n 1 " + hostname)
    print ("[DEBUG]", response)
    if response == 0:
        print (hostname, 'is up')
        row['status'] = 'Up'
    else:
        print (hostname, 'is down')
        row['status'] = 'Down'

#write results
with open("hosts.csv", "wb") as f:
    writer = csv.DictWriter(f, reader.fieldnames)
    # to maintain the same structure from the original file, rewrite header in original position
    writer.writeheader()
    print("[DEBUG] just before write rows")
    writer.writerows(rows)
    print("[DEBUG] after write rows")

Before instantiate csv.DictWriter, you can change the field names that you want to be in the new file:

newfieldnames = csvreader.fieldnames
lastfield = newfieldnames.pop() # remove last field
if 'field_name' in newfieldnames:
    newfieldnames.remove('field_name') # remove by field name
writer = csv.DictWriter(f, newfieldnames)
denisvm
  • 720
  • 3
  • 11