How to change a specific value of a specific key in text file using python

Question:

I would like to know how to replace a value of a specific key in a text file using python

I have this text file named passenger.txt have the following:

{'Civil ID':'1', 'Name':'Mike', 'DOB':'12/2/2000', 'Gender':'Male', 'Customs fine':'', 'Status':''}

I want to replace Status value to Sometext instead of blank, I already have a code but it replacing the key not the value. So, I’m wondering how to change the value not the key.

Here is the code:

passenger_db = "passenger.txt"
with open(passenger_db, "r+") as file:
  for single_line in f:
     x = single_line.replace('Status', 'Sometext')
     file.write(x)

I expect some one will help me.

Asked By: Kilmton Starvy

||

Answers:

It’s better to use JSON or pickle. But if you must:

import ast, pathlib
passenger_db = Path("passenger.txt")
data = ast.literal_eval(passenger_db.read_text())
data['Status'] = 'SomeText'
passenger_db.write_text(str(data))
Answered By: roeen30

You can use yaml module to parse each line to a dictionary then you can just update the value with key name

import yaml

with open('passenger.txt') as fp, open('output.txt', 'w') as fw:
  for line in fp:
    data = yaml.safe_load(line)
    data['Status'] = 'Some text'
    fw.write(str(data) + 'n')

But it’s better to use json file with list of objects
so you don’t need to parse each line

Answered By: deadshot

One of many solutions.

Input file passenger.txt

{'Civil ID':'1', 'Name':'Mike', 'DOB':'12/2/2000', 'Gender':'Male', 'Customs fine':'', 'Status':''}

Code:

from ast import literal_eval
passenger_db = "passenger.txt"
with open(passenger_db) as file:
    lines = [literal_eval(x) for x in file]

with open(passenger_db, "w") as file:
    for line in lines:
        line['Status'] = "Sometext"
        file.write(str(line))

Result:

{'Civil ID': '1', 'Name': 'Mike', 'DOB': '12/2/2000', 'Gender': 'Male', 'Customs fine': '', 'Status': 'Sometext'}

Another way to solve it:
The fileinput module of the Python standard library will rewrite a file inplace if you use the inplace=1 parameter:

import fileinput
import sys
passenger_db = "passenger.txt"
for line in fileinput.input('passenger.txt', inplace=1):
    sys.stdout.write(line.replace("'Status': ''", "'Status': 'Sometext'"))

Result:

{'Civil ID': '1', 'Name': 'Mike', 'DOB': '12/2/2000', 'Gender': 'Male', 'Customs fine': '', 'Status': 'Sometext'}
Answered By: user56700
lines = []
with open('passenger.txt') as f:
    for line in f.readlines():
        passenger = eval(line)

        # If you wish to update only certain strings
        if passenger['Civil ID'] == '1':
            passenger['Status'] = 'New status'

        lines.append(str(passenger))

with open('new_file.txt', 'w') as f:
    for line in lines:
        f.write(f'{line}n')

Explanation:

I’m afraid the only option for you is the following:

  1. Read the whole file
  2. Convert each line to a python object
  3. Replace a key in the object
  4. Convert it back to a sting
  5. Write the result to the file again
Answered By: Vladislav Pavkin

Use RegEx substitution

If you don’t feel like loading each line of data in Python dict object and modify the value (which is a totally fine way to do it), using RegEx would be a good alternative.

Regular expression is a very powerful tool when it comes to searching or manipulating string contents.

For the input txt file:

{'Civil ID':'1', 'Name':'Mike', 'DOB':'12/2/2000', 'Gender':'Male', 'Customs fine':'', 'Status':''}
{'Civil ID':'2', 'Name':'John', 'DOB':'12/2/2000', 'Gender':'Male', 'Customs fine':'', 'Status':'foo'}
{'Civil ID':'3', 'Name':'Mary', 'DOB':'12/2/2000', 'Gender':'Female', 'Customs fine':'', 'Status':'bar'}
import re


def set_values(filename: str, key: str, value: str):
    with open(filename) as f:
        text = f.read()
    updated_text = re.sub(f"(?<='{key}':').*(?='}})", value, text)
    with open(filename, 'w') as f:
        f.write(updated_text)


set_values('passenger.txt', 'Status', 'Sometext')

The script with replace all occurrences of the 'Status':'<any-text>' pattern with Sometext.

Result:

{'Civil ID':'1', 'Name':'Mike', 'DOB':'12/2/2000', 'Gender':'Male', 'Customs fine':'', 'Status':'Sometext'}
{'Civil ID':'2', 'Name':'John', 'DOB':'12/2/2000', 'Gender':'Male', 'Customs fine':'', 'Status':'Sometext'}
{'Civil ID':'3', 'Name':'Mary', 'DOB':'12/2/2000', 'Gender':'Female', 'Customs fine':'', 'Status':'Sometext'}

If you only want to modify one line instead of the whole file, just loop over the lines after reading the file and find the line you want to modify, then apply the regular expression substitution.

You can also tweak the RegEx pattern based on your need to substitute other content in the text file.

Answered By: James Chien
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.