I'm just learning to write. I set myself a task a few days ago, and today I completed its implementation. The task was to create a "backupper" (I was inspired just by my homework with "Byte of Python"): you specify from where and where the synchronization of all content will go. After that there is synchronization (copying, replacing and, if necessary, deleting). I would like to bring you my decision to defeat. As for me, it turned out, as for such a simple task, quite cumbersome. If anyone has any ideas for improving the code - making it more logical, elegant, and stripping away all the frills - I would be extremely grateful for any ideas and solutions.
#it took too much
import os
from dirsync import sync
import json
from pathlib import Path
import shutil
#block access to "memory"
print('\nHere are your backup paths ("Name":"From where we make backup">>>"Where we make backup"):\n')
with open('left.json', 'r', encoding='utf-8') as lreadmemory:
lmemory = json.load(lreadmemory)
for name in lmemory:
for n,l in name.items():
#print(n, ':', l)
with open('right.json', 'r', encoding='utf-8') as rreadmemory:
rmemory = json.load(rreadmemory)
for name2 in rmemory:
for a, b in name2.items():
if a==n:
print(' ',n, ':', '"', l, '"', '>>>', '"', b, '"')
while True:
filename = input('\n\n\You can enter the name of your old backup path, if you need new backups - enter "new"::')
## block for writing new values to memory
if filename == 'new':
while True:
newwayname = input('\Name:')
if newwayname == 'new':
print('Not "new"') # ingenious solution (not really)
else:
break
while True:
newwayfrom = input('From where we make backup:')
if os.path.isdir(newwayfrom) == True:
break
else:
print('Not dir')
while True:
newwayto = input('Where we make backup:')
if os.path.isdir(newwayto) == True:
break
else:
print('Not dir')
jsleft = {}
jsright = {}
jsleft[newwayname] = newwayfrom
jsright[newwayname] = newwayto
jleft = json.load(open('left.json', encoding='utf-8'))
jleft.append(jsleft)
json.dump(jleft, open('left.json', 'w'),indent=4)
jleft = json.load(open('right.json', encoding='utf-8'))
jleft.append(jsright)
json.dump(jleft, open('right.json', 'w'), indent=4)
#call-by-name block
while True:
hisname = input('\nEnter the name of the backup path you want to execute:')
with open('left.json', 'r', encoding='utf-8') as leftreadmemory:
memory_l = json.load(leftreadmemory)
for name_l in memory_l:
for al, bl in name_l.items():
if al == hisname:
left_way = bl
break
with open('right.json', 'r', encoding='utf-8') as rightreadmemory:
memory_r = json.load(rightreadmemory)
for name_r in memory_r:
for ar, br in name_r.items():
if ar == hisname:
right_way = br
break
break
while True:
copyornot = input('Copy? (Y/n):')
if copyornot == 'Y':
break
elif copyornot == 'n':
print('...')
continue
else:
print('(Y/n)')
#copy block
while True:
try:
sync(left_way, right_way, 'sync')
break
except NameError:
print('Invalid name specified')
break
#call-by-name block
else:
hisname = filename
while True:
with open('left.json', 'r', encoding='utf-8') as leftreadmemory:
memory_l = json.load(leftreadmemory)
for name_l in memory_l:
for al, bl in name_l.items():
if al == hisname:
left_way = bl
break
with open('right.json', 'r', encoding='utf-8') as rightreadmemory:
memory_r = json.load
for name_r in memory_r:
for ar, br in name_r.items():
if ar == hisname:
right_way = br
break
break
while True:
copyornot = input('Copy? (Y/n):')
if copyornot == 'Y':
break
elif copyornot == 'n':
print('...')
continue
else:
print('(Y/n)')
#copy block
while True:
try:
sync(left_way, right_way, 'sync')
break
except NameError:
print('invalid name specified')
break
# "excess" removal block for the right side
pl = Path(left_way)
pr = Path(right_way)
difference = (set(map(lambda p: p.relative_to(pr), pr.rglob('*'))) - set(
map(lambda p: p.relative_to(pl), pl.rglob('*'))))
if len(difference) > 0:
print('\nExcess:\n')
for a in difference:
a2 = Path(pr, a)
print(' ', a2)
while True:
copyornot = input('\nRemove? (Y/n):\n')
if copyornot == 'Y':
break
elif copyornot == 'n':
print('...')
continue
else:
print('(Y/n)')
for a in difference:
a2 = Path(pr, a)
if os.path.isfile(a2):
os.remove(a2)
if os.path.isdir(a2):
shutil.rmtree(a2)
print('\nI has worked conscientiously, now I can drink beer with a pure soul')
One way or another, I look forward to any criticism, comments, ideas in the comments.
Example 'left.json'
[
{
"1": "C:\\From_here"
}
]
Example 'right.json'
[
{
"1": "C:\\To_here"
}
]
2 Answers 2
Documentation
The first thing I noticed was that there is no documentation. You can add a docstring to the top of the code summarizing its purpose:
"""
Synchronization and backup of directories and files
"""
Add usage information, such as the input JSON files.
Comments
The next thing I noticed was the unexpected indentation of some of the comments. For example:
while True:
filename = input('\n\n\You can enter the name of your old backup path, if you need new backups - enter "new"::')
## block for writing new values to memory
The indentation is misleading because it looks like the while
loop ends
after one statement, but that is not the case.
The black program can be used to automatically format the code to add the proper indentation. It also adds consistent whitespace around operators.
Most of the comments are helpful. However, this comment can be deleted:
# it took too much
Also, delete all commented-out code to reduce clutter:
# print(n, ':', l)
This comment is vague:
#block access to "memory"
In this case, you can use complete sentences to explain what the code is doing.
Naming
The PEP 8 style guide recommends snake_case for variable names. For example:
lreadmemory
would be:
l_read_memory
Although, l
is vague, and you should replace it with something meaningful.
Similarly for lmemory
, rmemory
, etc.
Lower-case l
is a bad name for a variable because it is easily confused
with the number 1
, not to mention that it conveys little meaning:
for n,l in name.items():
DRY
The while
loop for the copyornot
variable is repeated twice.
You could move that code into a function:
def do_copy():
Input
Since the code calls input
several times, it is worth considering using
pyinputplus. This offers many
features for validating user input.
Simpler
In this line:
if len(difference) > 0:
there is no need for the comparison. This is simpler:
if len(difference):
Portability
I get a syntax error on this line with my version of Python:
newwayname = input('\Name:')
Perhaps your version of Python is more forgiving. To eliminate the error, I removed the backslash character:
newwayname = input('Name:')
while true is ok but you may consider while_running == True then have a input at the end to cancel in y eyes have break for any reason could cause unexpected things
-
1\$\begingroup\$ This answer is unclear; it is difficult to understand what advice you are offering as a code review. Edit the answer to use proper English grammar and add code formatting as needed. \$\endgroup\$toolic– toolic2025年03月14日 13:42:32 +00:00Commented Mar 14 at 13:42
Explore related questions
See similar questions with these tags.