I'm fairly new to programming and this is the 2nd thing I've done in python.
This code creates a /Tiles directory in the folder where the script is ran, then it makes an X (8) number of folders inside of /Tiles.
Inside of those 8 folders it makes a Y number of subfolders and downloads Z number of images per Y folder.
Y and Z are the same number but change depending on the X folder.
X folder 0 contains 2^0 Y folders and 2^0 Z images per Y folder.
Next X folder 2^1, etc until 8 folders or 2^7.
Any general or python specific advice for a newbie?
Also, any design advice?
I was thinking of having a loading bar of some sorts because it's ~20k images and was looking into this https://stackoverflow.com/questions/3173320/text-progress-bar-in-the-console
But in the end decided I just want to finish this up since I was done with the main functionality.
[..] means the code is on the same line but I made a new one for the purposes of reading here without scrolling.
Thanks.
import os
import urllib.request
import ctypes
print ("This script will download map tiles from [Redacted link]")
print ("The further it gets the more time it will take to fill the current folder.")
print ("Because the number of images increases exponentially.")
print ("You can check the progress by going into the latest folder.")
print ("When it is done the taskbar icon will flash and prompt you to close the window.")
# stores current directory
path = os.getcwd()
print ("The current working directory is {}.".format(path) + "\n")
# adds the names of the new directory to be created
path += "/Tiles/"
# defines the access rights
access_rights = 0o755
# creates the tiles directory
try:
os.mkdir(path, access_rights)
except OSError:
print ("Creation of the tiles directory {} failed.".format(path))
else:
print ("All files will be downloaded to {}.".format(path))
# for testing:
# print ("Successfully created the tiles directory {}".format(path))
# number of x subfolders
x_folders = 8
# number of y subfolders and z images - different folders have a
[..] # different number of subfolders amd images
yz_array = [2**0, 2**1, 2**2, 2**3, 2**4, 2**5, 2**6, 2**7]
# main loop
# creates the x directories
for x in range(x_folders):
try:
os.mkdir("{}/{}".format(path,x), access_rights)
except OSError:
print ("Failed to create the X directory - {}.".format(x))
break
except:
print("Something went wrong creating X folders.")
break
else:
print("Downloading images to {}{}.".format(path,x))
# creates the y directories
for y in range(yz_array[x]):
try:
os.mkdir("{}/{}/{}".format(path,x,y), access_rights)
except OSError:
print ("Failed to create the Y directory - {}.".format(y))
break
except:
print("Something went wrong creating Y folders.")
break
else:
pass
# downloads z images
for z in range(yz_array[x]):
try:
urllib.request.urlretrieve("[Redacted link]
[..]/{}/{}/{}.png" \
.format(x,y,z), "{}/{}/{}/{}.png".format(path,x,y,z))
except:
print("Something went wrong downloading Z images.")
break
else:
pass
print("Successfully filled folder {}{}.".format(path,x) + "\n")
print("Finished running.")
ctypes.windll.user32.FlashWindow(ctypes.windll.kernel32.
[..]GetConsoleWindow(),True) # flashes the taskbar icon
print("Press Enter to close")
input("\n")
1 Answer 1
Cool python exercise! And a nice job.
I'm going to assume you are using python3. There are some points of improvement:
- Multiline strings: In python you can create a string with more than one line using
"""
so you an put all of the printing in the beginning of your program in one print statement. - Pathlib: There is a library called pathlib which allows you to create multi platform path objects. Try to use it instead of concatenating strings yourself.
- Constants in capitals: Is
access_rights
a constant? Write it in capital letters if so (It's a normal naming convention). - String formatting: You can use
fstrings
instead offormat
, it looks much nicer and more readable (to me). So"Downloading images to {}{}.".format(path,x)
can now bef"Downloading images to {path}{x}."
. - List comprehension: you can create the
yz_array
using list comprehension, it is a bit complicated but it will look like:[2 ** x for x in range(8)]
- will get the same result! - Meaningful variable names: instead of
x
even usex_index
. - Meaningful exceptions: Using
Exception as e
you can print the system error, giving the user more information. - Logical error: Notice that even if there was an error in the file creation process you will still print "Successfully filled folder" which is not true. Add a boolean variable to prevent that.
- Multi Platform compatibility: You are probably using
windows
, but on otheros
your code will crush, by adding anothertry - catch
you can prevent that. You can also try and find theos
and create a matching case for windows.
Maybe:
- Functions: You can use functions to avoid the indentations.
- Spaces: According to
PEP8
you should add a space after a,
and you should not add space after a print statement. - Use type annotation: (Last but this one is my personal favourite) When your code gets complicated and you start to use function - Do not forget to read about
type annotations
.
Overall - greate code, nicely written.
Good luck and Have fun!
-
\$\begingroup\$ Appreciate the response! I'll look into all the suggestions and make adjustments. Thanks a lot. \$\endgroup\$Chiril Russu– Chiril Russu2020年02月24日 22:28:40 +00:00Commented Feb 24, 2020 at 22:28