1

I'm trying to write a program by change an open file, and I need to add a new line in the print.

In the open txt.file, it shows like this (I use"_" replace blank):

Name_____Height(m)_____Weight(kg)

Bill________1.58__________58

Mary_____1.65__________43

...

And now I want to add a new row like this: Name_____Height(m)_____Weight(kg)_____Age(year)<---The new vertical line

Bill________1.58__________58_____________15

Mary_____1.65__________43_____________17

And my code it's:


data_file = open("file.txt", "r")

print(data_file.read())

data_file.close()

So, how could I add another vertical line in the open file? Moreover, If I want to add more rows, how can I do this?


One more thing, I use the python 3.5

Sam
  • 191
  • 1
  • 8
Billzhai
  • 13
  • 3
  • This has been answered several times. See http://stackoverflow.com/questions/11070527/how-to-add-a-new-column-to-a-csv-file-using-python or http://stackoverflow.com/questions/23682236/add-a-new-column-to-an-existing-csv-file – John Karasinski Jun 06 '16 at 05:29

2 Answers2

1

I wrote a little class to do everything you asked for and more. Implementation examples are done at the bottom. Let me know if this works for you.

class Feed(object):
    def __init__(self, file_name, sep, naming_convention=None):
        self.file_name = file_name
        self.feed_item_naming = naming_convention
        self.sep = sep
        self.feed = self.load_feed()

    def get_head(self, file=None):#lmao...
        '''
            Get the header
            '''

        if not file:
            head = open(self.file_name).readline().split(self.sep)
        else:
            head = file[0].split(self.sep)
        return head

    def __repr__(self):
        return repr(self.feed)

    def load_feed(self):
        '''
            load a feed object
            set the key of each item to the naming convention
            if we have multiple item names we increment the name bill becomes bill_2 and then bill_3 etc...
            '''

        #first we open the file and grab the headers
        file = [x.rstrip() for x in open(self.file_name).readlines()]
        self.header = self.get_head(file)
        if not self.feed_item_naming and self.feed_item_naming not in self.header:
            self.feed_item_naming = self.header[0]
        data = {}
        for line in file[1:]:
            if line != '':
                line = line.split(self.sep)
                pos = line[self.header.index(self.feed_item_naming)]
                while pos in data:
                    try:
                        ending = int(pos[-1])+1
                        pos.replace(pos[-1], ending)
                    except:
                        pos = pos+'_2'
                data[pos] = {}
                for item in self.header:
                    data[pos][item] = line[self.header.index(item)]
        return data

    def unload_feed(self, file_name=None, sep=None):
        '''
            write the modified feed back out to a data file
            '''

        if not file_name:
            file_name = self.file_name
        if not sep:
            sep = self.sep

        with open(file_name, 'wb') as file:
            for i in self.header:
                if i != self.header[-1]:
                    file.write(i+sep)
                else:
                    file.write(i)
            file.write('\n')
            for i in self.feed:
                for x in self.header:
                    if x != self.header[-1]:
                        file.write(str(self.feed[i][x])+sep)
                    else:
                        file.write(str(self.feed[i][x]))
                file.write('\n')


    def add_key(self, key, default_value=None):
        '''
            Add a key to each of the items
            '''
        if key not in self.header:
            for i in self.feed:
                self.feed[i][key]=default_value
            self.header.append(key)

    def get_key_value(self, item, key):
        '''
            get the value for the items key
            '''

        return self.feed[item][key]

    def get_item(self, item):
        '''
            get an individual item
            '''

        return self.feed[item]

    def set_key_value(self, item, key, value):
        '''
            set the value of each items key
            {item:{key:value, key:value}, item...etc}
            '''

        self.feed[item][key] = value

    def set_key_values(self, item, key_value_dict):
        '''
            set multiple key values for an item
            '''

        for k,v in key_value_dict.iteritems():
            self.set_key_value(item, k, v)

    def add_item(self, item):
        '''
            Add a new item
            '''
        while item in self.feed:
            try:
                end = str(int(item[-1])+1)
                item = item.replace(item[-1], end)
            except:
                item = item+'_2'

        self.feed[item] = {}
        self.feed[item][self.feed_item_naming] = item
        for i in self.header:
            if i != self.feed_item_naming:
                self.feed[item][i] = None

f = Feed('file.txt', '_____', 'Name') #initialize a new feed object, make sure that all seperators are the same for each item in your file
f.add_item('Angela') #add a new item
f.set_key_values('Angela', {'Height(m)':5, 'Weight(kg)':123}) #set the new items height and weight
f.add_key('Position')#create a new key for each item
f.unload_feed() #write the feed back to the file
print(f)
TheLazyScripter
  • 2,541
  • 1
  • 10
  • 19
0

If by "add a new vertical line" you mean "add a new column" to your file, you can do this with the help of the csv module.

The code below works by reading the contents of your file as a list, making the changes, and then writing the updated list back to the file. You can add rows to your file this way, as well.

import csv

with open('file.txt', 'r') as f:
    reader = list(csv.reader(f, delimiter=' ')) # if your file is delimited by spaces, tabs, etc. 
                                                # include that value here.  It appears that 
                                                # your file is space-delimited, but that's 
                                                # just a guess based on the info in your question.
    for i,row in enumerate(reader):
        if i == 0:
            row.append('Age(year)')
        if i == 1:
            row.append('15')
        if i == 2:
            row.append('17')

with open('file.txt','w') as f:
    wr = csv.writer(f, delimiter=' ')
    for row in reader:
        wr.writerow(row)

# file.txt output:
# Name Height(m) Weight(kg) Age(year)
# Bill 1.58 58 15
# Mary 1.6 43 17

This code also uses with statements when working with your file. Using either with or close() (like you included in your question) is the correct practice when working with files. A with statement is easy to use because it closes your file automatically.

Daniel
  • 2,345
  • 4
  • 19
  • 36