python unicode replace MemoryError
Question: i want replace unicode character to a file with python

this is my code :

    
    
    with codecs.open('/etc/bluetooth/main.conf', "r", "utf8") as fi:
                mainconf=fi.read()
            forrep = ''.decode('utf8')
            for line in mainconf.splitlines():
                if('Name = ' in line):
                    forrep = line.split('=')[1]
            print 'name',type(name)
            print 'mainconf',type(mainconf)
            print 'forrep',type(forrep)
            mainconf = mainconf.replace(forrep, name)
            #mainconf = mainconf.replace(forrep.decode('utf8'),' '+name)
            with codecs.open('/etc/bluetooth/main.conf','w',"utf8") as fi:
                fi.write(mainconf)
    

but python always get me error `MemoryError`...

this out :

    
    
    name <type 'unicode'>
    mainconf <type 'unicode'>
    forrep <type 'unicode'>
    Traceback (most recent call last):
      File "WORK/Bluetooth/Bluetooth.py", line 359, in <module>
        if __name__ == '__main__':main()
      File "WORK/Bluetooth/Bluetooth.py", line 336, in main
        BLMan.SetAllHCIName(common.cfg.get('BLUETOOTH', 'HCI_DEVICE_NAME'))
      File "WORK/Bluetooth/Bluetooth.py", line 194, in SetAllHCIName
        mainconf = mainconf.replace(forrep, name)
    MemoryError
    


Answer: Iterate over the file object, you are storing the whole file content in memory
using `mainconf=fi.read()` :

    
    
    with codecs.open('/etc/bluetooth/main.conf', "r", "utf8") as fi:
        for line in fi:
    

You store all the lines with read then you store a list of all the lines using
splitlines so you are storing all the file content twice and as @abarnet
pointed out in a comment you then try to store a third copy with `mainconf =
mainconf.replace(forrep, name)`.

Iterating over the file object will give you a line at a time, if you need to
store the lines after replacing do so each time through the loop so at most
you will only have one copy of the file content in memory.

I have no idea what name is but writing to a tempfile will be the most
efficient way to do what you want:

    
    
    from tempfile import NamedTemporaryFile
    
    with open('/etc/bluetooth/main.conf') as fi, NamedTemporaryFile(dir=".", delete=False) as out:
        for line in fi:
            if line.startswith("Name ="):
                a, b = line.split("=",1)
                out.write("{} = {}".format(a, name.encode("utf-8")))
            else:
                out.write(line)
    
    move(out.name, '/etc/bluetooth/main.conf')
    

