2
\$\begingroup\$

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")
\$\endgroup\$
4
\$\begingroup\$

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 of format, it looks much nicer and more readable (to me). So "Downloading images to {}{}.".format(path,x) can now be f"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 use x_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 other os your code will crush, by adding another try - catch you can prevent that. You can also try and find the os 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!

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Appreciate the response! I'll look into all the suggestions and make adjustments. Thanks a lot. \$\endgroup\$ – Chiril Russu Feb 24 at 22:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.