An alternative to the accepted answer is to:
- Use
fileinput
with inplace=True
to modify the file in-place
- Use
csv.DictReader
to access the column via header instead of indices (This only works if the CSV has headers)
Test CSV:
Ip,Sites
127.0.0.1,10
127.0.0.2,23
127.0.0.3,50
Test Code:
import fileinput
with fileinput.input(files=('test.csv'), inplace=True, mode='r') as f:
reader = csv.DictReader(f)
print(",".join(reader.fieldnames)) # print back the headers
for row in reader:
if row["Ip"] == "127.0.0.2":
row["Sites"] = "30"
print(",".join([row["Ip"], row["Sites"]]))
The main difference is that you don't have to manually open the input file and create the output file, as inplace=True
already does that behind-the-scenes:
Optional in-place filtering: if the keyword argument inplace=True
is
passed to fileinput.input()
or to the FileInput
constructor, the file
is moved to a backup file and standard output is directed to the input
file (if a file of the same name as the backup file already exists, it
will be replaced silently). This makes it possible to write a filter
that rewrites its input file in place.
The loop goes over the CSV row-by-row (except for the header row), so you can do whatever processing you need on each row.
If you still want to retain the original, you could pass in a backup=".backup"
so that fileinput
creates a test.csv.backup file.
Also, note that with in-place editing, "standard output is directed to the input file", so print(..)
prints it out to the file instead of to the command line. If you want to actually print to the console, you need to specify stderr
as in print(..., file=sys.stderr)
.