function encrypt file - input & output to same file in python

626 views Asked by At

i have this script : http://pastebin.com/JypqErN5 in this moment the function working input output file :

encrypt_file(in_file, out_file, password):

need input output to same file, simile to this :

encrypt_file(in_file, password):

im try to make same name input output bat not encrypt file correctly.

the function is this :

def encrypt_file(input_file, output_file, password):
    with open(input_file, 'rb') as in_file, open(output_file, 'wb') as out_file:
        encrypt(in_file, out_file, password)

how can i make this edits ? thanks all

1

There are 1 answers

0
abarnert On BEST ANSWER

You can't generally read from and write to a file at the same time.

So, you have two basic options.


First, you can read into memory, then encrypt, then write back out. Hopefully you have an encrypt function that works on strings rather than files. Since you've tagged this pycrypto, and all of its engines work on strings, this should be trivial. But if you have to use files, you can usually use BytesIO (or, for 2.x, cStringIO.StringIO), which wraps up a byte string in a file-like object, like this:

def encrypt_file(path, password):
    temp = io.BytesIO()
    with open(path, 'rb') as in_file:
        encrypt(in_file, temp, password)
    with open(path, 'wb') as out_file:
        out_file.write(temp.getvalue())

This is dead simple, but of course it could be a problem if your files are gigantic.


Or you can write to a NamedTemporaryFile, then replace the original file with the temporary:

def encrypt_file(path, password):
    dir = os.path.dirname(path)
    with open(path, 'rb') as in_file, tempfile.NamedTemporaryFile(dir=dir, delete=False) as out_file:
        encrypt(in_file, temp, password)
    os.replace(temp.name, path)

This has some major advantages over the other method—it doesn't necessarily take a ton of memory (that depends on how encrypt is written), and there's no chance of leaving behind a partially-written file if you pull the plug (os.replace is atomic—it either happens completely, or not at all). But it's a little more complicated. And, before Python 3.3, there was no replace function. On Unix, rename works just as well. On Windows… well, that's a whole mess.