7

Is there a way, in Python, to modify a single line in a file without a for loop looping through all the lines?

The exact positions within the file that need to be modified are unknown.

kojiro
  • 74,557
  • 19
  • 143
  • 201
tew
  • 2,723
  • 5
  • 23
  • 35
  • How do you know what line it is? If you know the exact byte position, sure. If not, it's not as clear. – Daniel DiPaolo Jun 23 '11 at 16:14
  • 3
    Step back from Python and think about how files are stored (conceptually, ignoring fragmentation and file system details) - as a continuous array of bytes. In this model, to ass or remove something in the middle means moving all bytes that come afterwards. There may be a way to hide this in your Python code, but it will still happen under the hood. Especially since it sounds you'll have to check each line to know if and how you want to modify it. –  Jun 23 '11 at 16:15
  • Say I have unknown line length and no fixed positions. – tew Jun 23 '11 at 17:35
  • Given it's impossible to do this without iterating the file under those rules (the only way to avoid it is if you're replacing `n` bytes with exactly `n` other bytes, and you know exactly where those `n` bytes begin), this ends up being a functional duplicate of [Editing specific line in text file in Python](https://stackoverflow.com/q/4719438/364696) – ShadowRanger Nov 22 '22 at 20:50

3 Answers3

5

Unless we're talking about a fairly contrived situation in which you already know a lot about the file, the answer is no. You have to iterate over the file to determine where the newline characters are; there's nothing special about a "line" when it comes to file storage -- it all looks the same.

senderle
  • 145,869
  • 36
  • 209
  • 233
  • 1
    As an aside, you might find that using a [`mmap`](http://docs.python.org/library/mmap.html) object will make the task easier. And [`linecache`](http://docs.python.org/release/3.1.3/library/linecache.html) uses a cache to emulate line-level random read access. – senderle Jun 23 '11 at 16:34
5

This should work -

f = open(r'full_path_to_your_file', 'r')    # pass an appropriate path of the required file
lines = f.readlines()
lines[n-1] = "your new text for this line"    # n is the line number you want to edit; subtract 1 as indexing of list starts from 0
f.close()   # close the file and reopen in write mode to enable writing to file; you can also open in append mode and use "seek", but you will have some unwanted old data if the new data is shorter in length.

f = open(r'full_path_to_your_file', 'w')
f.writelines(lines)
# do the remaining operations on the file
f.close()

However, this can be resource consuming (both time and memory) if your file size is too large, because the f.readlines() function loads the entire file, split into lines, in a list.
This will be just fine for small and medium sized files.

Pushpak Dagade
  • 6,280
  • 7
  • 28
  • 41
  • 2
    This is correct in that it is often the right way to do this; however, it does not answer the OP's actual question, since `readlines` iterates over all the lines in the file. – senderle Jun 23 '11 at 16:40
  • I think walle1357 does not want to himself iterate over the file, its fine for him if some function does it. Otherwise, the question asked is too content specific. – Pushpak Dagade Jun 23 '11 at 16:43
  • @Guanidene, perhaps you're right -- the question is a bit vague, isn't it? – senderle Jun 23 '11 at 16:47
  • @senderle, yes it not clear what he exactly wants. @walle1357, please make it clear what you exactly want. – Pushpak Dagade Jun 23 '11 at 16:50
  • If a function does the work for me that would be fine. This answer answers my question though. – tew Jun 24 '11 at 00:02
3

Yes, you can modify the line in place, but if the length changes, you will have to rewrite the remainder of the file.

You'll also need to know where the line is, in the file. This usually means the program needs to at least read through the file up to the line that needs to be changed.

There are exceptions - if the lines are all fixed length, or you have some sort of index on the file for example

John La Rooy
  • 295,403
  • 53
  • 369
  • 502