-3

I have the following code in the file called stacktest.py inside my work folder in Visual Studio Code:

a = 'home'
b = 'hotel'
c = 'flat'

print(b)

And I would like to use another Python file to edit this previous file, for example change:

b = 'hotel'

For:

b = 'new value'

So the new saved file would look like this:

a = 'home'
b = 'new value'
c = 'flat'

print(b)

How should I go about doing this?

pppery
  • 3,731
  • 22
  • 33
  • 46
Digital Farmer
  • 1,705
  • 5
  • 17
  • 67
  • 1
    Are you doing this purely as an academic exercise? Or do you plan to actually change the contents of Python files to manipulate how scripts run - because if that's the case, you absolutely should not and should look instead at formats like csv or json to store values for easy access from your scripts. – Grismar Feb 06 '22 at 05:16
  • 1
    If you do have a valid use case, you should take a look at previous questions on the subject and ask a more specific question if those give you trouble, because as it stands, you're just asking for recommendations on software and libraries (or asking a very trivial question and the answer could be "write a regex") https://stackoverflow.com/questions/768634/parse-a-py-file-read-the-ast-modify-it-then-write-back-the-modified-source-c – Grismar Feb 06 '22 at 05:18
  • 1
    As @Grismar said, other aproaches would be much more suitable if you are creating stacktest.py. Can you elaborate on your circumstances? Do you have full control of the file format? – Chris Larson Feb 06 '22 at 05:20
  • Hi @Grismar That's why I put it on the ```SuperUser``` community, because it was just a recommendation request, to group options into a case study and understand the options that exist. But they migrated the question here and it ended up being very simple question! – Digital Farmer Feb 06 '22 at 05:39
  • Hello @ChrisLarson , the idea really was to leave it open to analyze the options indicated by the ```SuperUser members```, basic recommendations to be used. But they migrated to ```StackOverflow``` which is geared towards robust doubts. – Digital Farmer Feb 06 '22 at 05:40
  • @BrondbyIF Got it! Perhaps my answer will offer a little insight towards considering a more pythonic approach. Cheers. – Chris Larson Feb 06 '22 at 06:04

2 Answers2

1

Open in w+ to rewrite a line, note that if the new line has less characters than the line to replace, you will need to copy the entire contents of the file, manually replace it in a list, then rewrite it.

with open("file.py", 'w+') as f:
    # jump to a certain line with .seek()
    f.seek(lineNumber)
    f.write("what you want the line to be")
1

You can, of course, do what you ask, as you presented:

# read file and assign lines as list to variable stacktest_dict
#   stripping line feed from each line
with open('stacktest.py') as stacktest:
 stacktest_list = [line.strip() for line in stacktest.readlines()]

# replace string in chosen line with new string
for line in stacktest_list:
    if line == "b = 'hotel'":
        index = stacktest_list.index(line)
        line = line.replace('hotel', 'new value')
        stacktest_list[index] = line

# write lines with linefeeds added back to file
#  using an f-string
with open('stacktest.py', 'w') as stacktest:
    stacktest.writelines([f"{line}\n" for line in stacktest_list])

This is a very basic, rudimentary solution, meant to show that it can be done.

However, Python offers much better, and much more efficient and performative approaches. Personally, assuming you are creating everything, and there aren't esoteric reasons for doing things as presented in the question, I'd use a dictionary, stored as JSON, along the following lines:

# Create dict and write to file stacktest_dict.py
stacktest_list = {'a': 'home', 'b': 'hotel', 'c':'flat'}
with open('stacktest_dict.py', 'w') as stacktest_dict:
    json.dump(stacktest_list, stacktest_dict)

# read file and assign to variable stacktest_dict
with open('stacktest_dict.py', 'r') as stacktest_dict_in:
    stacktest_dict = json.load(stacktest_dict_in)

# assign new value for key 'b' in dict
stacktest_list['b'] = 'new value'

# write dict back to file
with open('stacktest_dict.py', 'w') as stacktest_dict:
    json.dump(stacktest_list, stacktest_dict)

# read file and assign to variable stacktest_dict
with open('stacktest_dict.py', 'r') as stacktest_dict_in:
    stacktest_dict = json.load(stacktest_dict_in)

# print the dict
print(stacktest_list)

# print the value of dict key 'b'
print(stacktest_list['b'])

In this scenario, you are reading and writing a JSON file, and working with the data as a native object that Python understands (a dictionary). This approach will save you time, both personally and computationally, and headaches going forward.

The scenario you've suggested, I'd present, is a perfect case for using a dictionary, stored, and read, as JSON. For further reference, see:

https://docs.python.org/3/tutorial/datastructures.html#dictionaries

Chris Larson
  • 1,684
  • 1
  • 11
  • 19
  • replace `stacktest.readlines()` with `stacktest` – rioV8 Feb 06 '22 at 14:01
  • That will, of course, work. However, timing the two gives: `stacktest_list = [line.strip() for line in stacktest.readlines()]: 0.0012340545654296875` `stacktest_list = [line.strip() for line in stacktest]: 0.004891157150268555` – Chris Larson Feb 07 '22 at 16:34