Since you are using Python 3.4, I would suggest replacing all the magic numbers with IntEnum.
This will make your code easier to understand and easier to modify if necessary.
And a benefit of using enums is that you cannot accidentally change their values, as you can with variables.
Consider this code;
import os
from hashlib import sha256
def compare(src, dest):
"""
Compare two files.
Arguments
src: Path of the source file.
dest: Path of the destination file.
Returns:
0 if source and destination are different
1 source and destination are identical
2 destination doesn't exist
3 source doesn't exist
"""
xsrc, xdest = os.path.exists(src), os.path.exists(dest)
if not xsrc:
return 3
if not xdest:
return 2
with open(src, 'rb') as s:
csrc = sha256(s.read()).digest()
if xdest:
with open(dest, 'rb') as d:
cdest = sha256(d.read()).digest()
else:
cdest = b''
if csrc == cdest:
return 1
return 2
This code in itself is not unclear. It is documented and all.
But once you try and use the return value, you'll constantly have to refer to the docs.
Can you tell why the code below does what it does? Not without referring to the documentation for compare.
res = compare(file_a, file_b)
if res == 1 or res == 3:
pass
elif res == 0:
# copy file_a to file_b
Now look at this;
import os
from hashlib import sha256
from enum import IntEnum
class Cmp(IntEnum):
differ = 0 # source and destination are different
same = 1 # source and destination are identical
nodest = 2 # destination doesn't exist
nosrc = 3 # source doesn't exist
def compare(src, dest):
"""
Compare two files.
Arguments
src: Path of the source file.
dest: Path of the destination file.
Returns:
Cmp enum
"""
xsrc, xdest = os.path.exists(src), os.path.exists(dest)
if not xsrc:
return Cmp.nosrc
if not xdest:
return Cmp.nodest
with open(src, 'rb') as s:
csrc = sha256(s.read()).digest()
if xdest:
with open(dest, 'rb') as d:
cdest = sha256(d.read()).digest()
else:
cdest = b''
if csrc == cdest:
return Cmp.same
return Cmp.differ
So if you now try using it, it looks like this;
res = compare(file_a, file_b)
if res == Cmp.same or res == Cmp.nosrc:
pass
elif res == Cmp.differ:
# copy file_a to file_b
You can understand this without referring to the docs for compare. You probably won't even have to check on the specifics of the Cmp enum.