0

I have a template txt file. This txt file is to be written as 10 new files but each with some characters changed according to a list of arbitrary values:

with open('template.txt') as template_file:
     template = template_file.readlines()
     for i in range(10):
          with open('output_%s.txt' % i, 'w') as new_file:
               new_file.writelines(template_file)

The length of the list is the same as the number of new files (10).

I am trying to replace part of the 2nd line of each new file with the value in my list.

So for example, I want line 2, positions [5:16] in each new file replaced with the respective value in the list..

File 0 will have element 0 of the list File 1 will have element 1 of the list etc..

I tried using the replace() method:

list = [element0, element1, etc...element9]

for i in template_file:
    i.replace(template_file[2][5:16], list_element)

But it will only replace all the files with the first list element... It wont loop over.

Any help appreciated

2
  • Where does list_element come from? Commented Mar 20, 2018 at 12:28
  • from the list... I know it's not right.. thats where the issue is... I want each element in 'list' (i.e list_element) to replace characters in each iteration of new txt file Commented Mar 20, 2018 at 12:29

2 Answers 2

1

There are a couple of problems I can find which prevent your code from working:

  • You should write template out, which is a list of lines, not template_file, which is a file object
  • In Python, strings are immutable, meaning they cannot be changed. The replace function does not change the string, it returns a new copy of the string. Furthermore, replace will replace a substring with a new text, regardless of where that substring is. If you want to replace at a specific index, I suggest to slice the string yourself. For example:

    line2 = '0123456789ABCDEFG'
    element = '-ho-ho-ho-'
    line2 = line2[:5] + element + line2[16:]
    # line2 now is '01234-ho-ho-ho-G'
    
  • Please do not use list as a variable name. It is a type, which can be used to construct a new list as such:

    empty = list()         # ==> []
    letters = list('abc')  # ==> ['a', 'b', 'c']
    
  • The expression template_file[2][5:16] is incorrect: First, it should be template, not template_file. Second, the second line should be template[1], not template[2] since Python list are zero based

  • The list_element variable is not declared in your code

Solution 1

That being said, I find that it is easier to structure your template file as a real template with placeholders. I'll talk about that later. If you still insist to replace index 5-16 of line 2 with something, here is a solution I tested and it works:

with open('template.txt') as template_file:
    template = template_file.readlines()
    elements = ['ABC', 'DEF', 'GHI', 'JKL']
    for i, element in enumerate(elements):
        with open('output_%02d.txt' % i, 'w') as out_file:
            line2 = template[1]
            line2 = line2[:5] + element + line2[16:]
            for line_number, line in enumerate(template, 1):
                if line_number == 2:
                    line = line2
                out_file.write(line)

Notes

  • The code writes out all lines, but with special replacement applies to line 2
  • The code is clunky, nested deeply
  • I don't like having to hard code the index numbers (5, 16) because if the template changes, I have to change the code as well

Solution 2

If you have control of the template file, I suggest to use the string.Template class to make search and replace easier. Since I don't know what your template file looks like, I am going to make up my own template file:

line #1
This is my ${token} to be replaced
line #3
line #4

Note that I intent to replace ${token} with one of the elements in the code. Now on to the code:

import string

with open('template.txt') as template_file:
    template = string.Template(template_file.read())
    elements = ['ABC', 'DEF', 'GHI', 'JKL']
    for i, element in enumerate(elements):
        with open('output_%02d.txt' % i, 'w') as out_file:
            out_file.write(template.substitute(token=element))

Notes

  • I read the whole file in at once with template_file.read(). This could be a problem if the template file is large, but previous solution als ran into the same performance issue as this one
  • I use the string.Template class to make search/replace easier
  • Search and replace is done by substitute(token=element) which said: replace all the $token or ${token} instances in the template with element.
  • The code is much cleaner and dare I say, easier to read.

Solution 3

If the template file is too large to fit in memory at once, you can modify the first solution to read it line-by-line instead of reading all lines in at once. I am not going to present that solution here, just a asuggestion.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much for your eloquent answer. I think solution 2 is the best way to go about it for my needs. Looks like a very useful library. Thanks again!
0

Looks like you need

list = [element0, element1, etc...element9]
for i in list:
    template_file = template_file.replace(template_file[2][5:16], i)

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.