4

More details below:

1st line

2nd line

3rd line

4th line

...

Now want to insert a new line named zero line before 1st line. File looks like below:

zero line

1st line

2nd line

3rd line

4th line

...

I know sed command can do this work, but how to do it using python? Thanks

Jason
  • 3,237
  • 4
  • 26
  • 28
  • You may want to check the question I've asked a year ago. It's answered by Alex Martelli and S.Lott, both are great Python gurus -- http://stackoverflow.com/questions/1325905/inserting-line-at-specified-position-of-a-text-file-in-python – Wang Dingwei Mar 13 '11 at 07:08
  • @Wang Dingwei Yeah, thank you Dingwei!~ – Jason Mar 13 '11 at 07:23

5 Answers5

7

you can use fileinput

>>> import fileinput
>>> for linenum,line in enumerate( fileinput.FileInput("file",inplace=1) ):
...   if linenum==0 :
...     print "new line"
...     print line.rstrip()
...   else:
...     print line.rstrip()
...
kurumi
  • 25,121
  • 5
  • 44
  • 52
  • you can use fileinputs' .isfirstline() instead of using linenum == 0 – dting Mar 13 '11 at 06:56
  • This won't work for empty files. You could use `print line,` (note: comma) instead of `print line.rstrip()` the latter might remove too much whitespace. Why don't you use `fileinput.input(inplace=1)`? – jfs Mar 13 '11 at 15:05
  • I've added an implementation that leaves original data intact (except prepending a line) http://stackoverflow.com/questions/5287762/how-to-insert-a-new-line-before-the-first-line-in-a-file-using-python/5290636#5290636 – jfs Mar 14 '11 at 07:10
5

this might be of interest

http://net4geeks.com/index.php?option=com_content&task=view&id=53&Itemid=11

adapted to your question:

# read the current contents of the file
f = open('filename')
text = f.read()
f.close()
# open the file again for writing
f = open('filename', 'w')
f.write("zero line\n\n")
# write the original contents
f.write(text)
f.close()
  • Open the file and read the contents into 'text'.

  • Close the file

  • Reopen the file with argument 'w' to write

  • Write text to prepend to the file

  • Write the original contents of the file to the file

  • Close file

Read the warnings in the link.

edit:

But note that this isn't entirely safe, if your Python session crashes after opening the file the second time and before closing it again, you will lose data.

dting
  • 38,604
  • 10
  • 95
  • 114
  • You could inline warnings from net4geeks in your answer. The fact that the code might **lose data** is important enough and it is resilient to a linkrot. See my answer for a version that doesn't require to load the whole file in memory http://stackoverflow.com/questions/5287762/how-to-insert-a-new-line-before-the-first-line-in-a-file-using-python/5290636#5290636 – jfs Mar 14 '11 at 07:08
4

Here's an implementation that fixes some deficiencies in other approaches presented sofar:

It mimics fileinput's error handling:

import os

def prepend(filename, data, bufsize=1<<15):
    # backup the file
    backupname = filename + os.extsep+'bak'
    try: os.unlink(backupname) # remove previous backup if it exists
    except OSError: pass
    os.rename(filename, backupname)

    # open input/output files,  note: outputfile's permissions lost
    with open(backupname) as inputfile, open(filename, 'w') as outputfile:
        # prepend
        outputfile.write(data)
        # copy the rest
        buf = inputfile.read(bufsize)
        while buf:
            outputfile.write(buf)
            buf = inputfile.read(bufsize)

    # remove backup on success
    try: os.unlink(backupname)
    except OSError: pass

prepend('file', '0 line\n')

You could use cat utility if it is available to copy the files. It might be more efficient:

import os
from subprocess import PIPE, Popen

def prepend_cat(filename, data, bufsize=1<<15):
    # backup the file
    backupname = filename + os.extsep+'bak'
    try: os.unlink(backupname)
    except OSError: pass
    os.rename(filename, backupname)

    # $ echo $data | cat - $backupname > $filename
    with open(filename, 'w') as outputfile: #note: outputfile's permissions lost
        p = Popen(['cat', '-', backupname], stdin=PIPE, stdout=outputfile)
        p.communicate(data)

    # remove backup on success
    if p.poll() == 0:
        try: os.unlink(backupname)
        except OSError: pass

prepend_cat('file', '0 line\n')
Community
  • 1
  • 1
jfs
  • 399,953
  • 195
  • 994
  • 1,670
1
with open(filename, 'r+') as f:
    lines = f.readlines()     
    lines.insert(0, 'zero line\n')   
    f.seek(0)                 
    f.writelines(lines)  
Zorro
  • 1,085
  • 12
  • 19
0

code

L = list()
f = open('text2.txt', 'r')
for line in f.readlines():
        L.append(line)
L.insert(0,"Zero\n")
f.close()

fi = open('text2.txt', 'w')
for line in xrange(len(L)):
        fi.write(L[line])

fi.close()

text2.txt

Hello
The second line
3
4
5
6

output

Zero
Hello
The second line
3
4
5
6

This can be memory heavy and time consuming for large files however.

If you are worried about something like 31st line, I would just do a mod%10 on the num, to get a more accurate version.

Let me know if this helps, or if you want a better version. Also, if you want a better formatting, look into ljust and rjust for left and right justify.

Jim
  • 3,236
  • 8
  • 33
  • 43
  • I'm pretty sure the original question is asking how to prepend lines before the start of the file. Your answer is just numbering the lines of a file which doesn't look like what hes asking for. Also you can use a list comprehension to generate that list. `[ line for line in f.readlines() ]` if you really want to generate a list of lines in f. – dting Mar 13 '11 at 06:30