0

I have a python file named constants.py with the following contents

from pytestLoop.config.testdata_005_connect_for_bank_statements import *

xpath_username="//div[text()='"+uname+"']"
pswd="//div[@id='password']"

# this is the end of the file.

I have another python file called alterConstants.py with the following contents

def changeConstants(fname):
    f = open("pytestLoop/config/constants.py",'r+')
    line = f.read()
    text=(line[line.index('config.') + 7:line.index(' import')])
    linenew = line.replace(text, fname)
    f.seek(0)
    f.write(linenew)
    f.close()

changeConstants("testdata_001")

after i execute the above alterConstants.py file, this is the content of constants.py

from pytestLoop.config.testdata_001 import *

xpath_username="//div[text()='"+uname+"']"
pswd="//div[@id='password']"

# this is the end of the file.his is the end of the file.

my initial goal is to change the line from pytestLoop.config.testdata_005_connect_for_ban_statementsimport * to import whatever filename I pass in the changeConstants function in alterConstants.py which is working fine

but python also writes some additional characters to the last line of the constants.py file

  1. Can someone please explain why does this happen ?
  2. Also please suggest on How to fix this issue.

Thanks in advance.

Fuze Test
  • 31
  • 6

2 Answers2

4

It's not writing extra characters, it's leaving behind the original characters from the older, larger file. You need to truncate the file to the new length to remove the extra content:

def changeConstants(fname):
    with open("pytestLoop/config/constants.py",'r+') as f:
        line = f.read()
        text = line[line.index('config.') + 7:line.index(' import')]
        linenew = line.replace(text, fname)
        f.seek(0)
        f.write(linenew)
        f.truncate()  # Trims file to match the current file offset

If the new file data is larger, the truncate doesn't do anything, but when the data is shorter, it trims the file down to match the file offset produced by writing the new data.

I also changed your code to use with to manage file lifetime (removing the need to explicitly close it, and guaranteeing it gets closed even if an exception occurs during processing).

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
  • Perfect. Thanks for the explanation. I wasn't aware that python writes the remaining characters produced from the difference. Thanks a lot. :) – Fuze Test Aug 21 '20 at 15:19
  • 1
    @FuzeTest Python does not write those remaining characters. If you only ``seek(0)``, you never tell Python to *remove* them in the first place. Everything that is not overwritten by a new ``write`` remains. – MisterMiyagi Aug 21 '20 at 16:44
  • @MisterMiyagi : oh okay, understood, Thanks – Fuze Test Aug 21 '20 at 16:56
1

Instead of seeking back to the start of the file (which leaves the old content intact), open the file again for writing.

def changeConstants(fname):
    with open("pytestLoop/config/constants.py",'r') as f:
        line = f.read()
    text=(line[line.index('config.') + 7:line.index(' import')])
    linenew = line.replace(text, fname)
    with open("pytestLoop/config/constants.py",'w') as f:
        f.write(linenew)

Opening a file in write mode automatically replaces the old content.

MisterMiyagi
  • 44,374
  • 10
  • 104
  • 119