I work with YML files that include SIDs and the following structure:

  "2": "content a" # key: comment 
  "3": "content b" # key: comment 
  "4": "content c" # key: comment 
  "5": "content d" # key: comment 
  "6": "content e" # key: comment 

Usually, I have to remove some strings (note I never remove the number 1 or 2) so my new file looks like this:

  "2": "content a" # key: comment 
  "3": "content b" # key: comment 
  "5": "content d" # key: comment 
  "6": "content e" # key: comment

I need to rearrange the SIDs in order to have a sequence without any gap (in this case 2, 3, 4, 5, 6) independently on the content. For that reason I have written the following script. It works properly but I need to bring it into production so I need your help to reduce its complexity, make it clear and simpler or any advice you may have for a beginner (in both, Python and Stack Exchange).

import re, os

file=input ('YML file name: ')

#read the file and store its content as a list
os.chdir('/home/balaclava/Desktop/Scripts/YML fixer/')
rdfile= open(file)

#list to store the reviewed strings

#Get the second string SID as reference
numRegex = re.compile(r'\d+')
global refnum

#Loop for each string (-2 due to the two first string are excluded)
for i in range(len(cont)-2):              
#If the SID is correct, add item to newlist, else, fix it and add the item to the list.              
    if temp == (refnum+1):              
        temp= (refnum+1)       
        change=numRegex.sub(str(temp), cont[i+2])
    refnum += 1

#overwrite the file with the newlist content
with open (file,'w') as finalfile:
  • 1
    \$\begingroup\$ Instead of attacking this with regexes, why not just do a yaml.load to bring it in, and modify it using regular python operations on the resulting data structure? It would be clear, and there would be no risk of corrupting the format. \$\endgroup\$
    – aghast
    Mar 15, 2019 at 4:01
  • \$\begingroup\$ @AustinHastings, yaml.load would not keep the comments. \$\endgroup\$
    – Balaclava
    Mar 17, 2019 at 17:52

1 Answer 1


You could use rumael.yaml, it can preserve comments. https://stackoverflow.com/questions/7255885/save-dump-a-yaml-file-with-comments-in-pyyaml#27103244

Moreover, you want to be a better python developer (or maybe pythonist?) I can give you some tips:

Content duplication You are storing the file content inside cont and after closing the file you are duplicating that info in a new variable newfile I think that is an unnecessary process in this situation. You could store all the data in cont and just modify the lines needed. You can replace the entire if-else by:

    if temp != (refnum+1):              
        temp= (refnum+1)       
        change=numRegex.sub(str(temp), cont[i])
        cont[i] = change

For loop's range Change your range call in the for loop to range(2, len(cont)): Now inside the loop you can access the current line with simply cont[i] it's more readable and efficient.

As with i's range you are accessing refnum always with a +1. By initializing it as refnum=int(act.group()) +1 your code saves that operations inside the loop. Another thing that you can do is do the +=1 increment at the beginning of the loop.

File management You don't need to manually close files when using with statement you can remove finalfile.close(). Another thing, you are using with in the when writing but not when reading, think about always use the same method.

More things can be changed but I think that's enough for now.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.