Minimizing open-close scenario I have the following code in Python which opens and closes a file in every iteration (using with keyword). In 95 % of iterations the file will be the same, so there's no need to open and close it again. Is it possible to optimize it if this optimization has sense?

import sys
import re

def createFileName(str, index, number_of_words, suffix):
  pattern = re.compile("[a-zA-Z]+")
  matchList = re.findall(pattern, str)
  matchList = [x.lower() for x in matchList]
  matchList = matchList[0:number_of_words]
  return index + "_".join(matchList) + suffix



if __name__ == "__main__":

  d = [("aaa", True), ("bbb x yyy aa" False), ("ccc aa", False), ("ddd bbb", True), ("eee ddd", False), ("fff x a b" True)] # this list of tuples is just for illustration, it will be usually much bigger.      

  fileName = createFileName(d[0][0], "00", 3, ".txt")
  with open(fileName, "a") as f:
    f.write(d[0][0] + "\n")
  i = 1
  for x in d[1:]:
    if x[1]:
      fileName = createFileName(x[0], "%02d" % i, 3, ".txt")
      i = i + 1
    with open(fileName, "a") as f:
      f.write(x[0] + "\n")
I think this is one of those rare case where with hits its limits and you should be better served with a try: ... finally.
You can open the first file, and wraps the rest of the operations into a
try:
    # rest of the operations
finally:
    f.close()

Then, each time the fileName need to change, you f.close() and f = open(...) again. This way, you only close the file when you won't use it anymore.
As for the rest of the code:

use 4 spaces per indentation level
use snake_case for variable and functions names
use unpacking to extract and give a meaningful name to the 2 components of the items in your list
create pattern as a global variable as there is no added value to compile it each time you call createFileName
you can avoid copying d when you slice it if you use iter

Proposed improvements
import sys
import re


PATTERN = re.compile(&quot;[a-zA-Z]+&quot;)


def create_file_name(string, index, number_of_words, suffix):
    matches = [x.lower() for x in re.findall(PATTERN, string)]
    return '{:02}{}.{}'.format(index, '_'.join(matches[:number_of_words]), suffix)



if __name__ == &quot;__main__&quot;:
    d = [(&quot;aaa&quot;, True), (&quot;bbb x yyy aa&quot; False), (&quot;ccc aa&quot;, False), (&quot;ddd bbb&quot;, True), (&quot;eee ddd&quot;, False), (&quot;fff x a b&quot; True)] # this list of tuples is just for illustration, it will be usually much bigger.      

    iterator = iter(d)
    file_index = 0
    name, _ = next(iterator)
    filename = create_file_name(name, file_index, 3, 'txt')
    f = open(filename, 'a')
    try:
        f.write(name + '\n')
        for name, new_file in iterator:
            if new_file:
                file_index += 1
                filename = create_file_name(name, file_index, 3, 'txt')
                f.close()
                f = open(filename, 'a')
            f.write(name + '\n')
    finally:
        f.close()