On 06/10/2016 03:52 PM, mad scientist jr wrote:
Is this group appropriate for that kind of thing?
(If not sorry for posting this here.)

So I wanted to start learning Python, and there is soooo much information 
online, which is a little overwhelming. I really learn best from doing, 
especially if it's something actually useful. I needed to create a bunch of 
empty folders, so I figured it was a good exercise to start learning Python.
Now that it's done, I am wondering what kind of things I could do better.
Here is the code:

It is FAR too complicated -- it's BASIC written Python.  Python is MUCH easier.

First a couple of general comments...

Drop the Hungarian notation!! Python uses dynamic typing. Variables do NOT have a type, the data they hold have types, but not the variable itself. ANY variable can hod ANY data type at ANY time. And Python uses duck typing -- get used to it.

Generally you should put all the imports at the beginning of the program, NOT in each function. A possible exception could be if an import is only used in one function.

############################################################################################################################################################
# GLOBAL VALUES
sForPythonVersion="3"
#sFolderPathTemplate = "c:\\myscripts\\MP3 Disc <iCount/>"
sFolderPathTemplate = "c:\\temp\\MP3 Disc <iCount/>"
iFromCount = 1
iToCount = 250
iCountWidth = 3

Drop the <iCount/> from the template string.  (More on this below.)

################################################################################################################################################################
# SUPPORT FUNCTIONS

# 
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
def is_string(myVar): # is_string IS MORE READABLE THAN isinstance (PLAIN 
ENGLISH!)
     #PYTHON 3 IS NOT LIKING THIS: return ( isinstance(myVar, str) or 
isinstance(myVar, unicode) )
     #PYTHON 3 IS NOT LIKING THIS: return isinstance(myVar, basestr)
     return isinstance(myVar, str)

Not necessary.

# 
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
# THIS IS SOME SAMPLE FUNCTION FROM A BOOK I AM READING "PYTHON IN EASY STEPS"
def strip_one_space(s):
     if s.endswith(" "): s = s[:-1]
     if s.startswith(" "): s = s[1:]
     return s

???  Is this used anyplace?  Delete it.

# 
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
def get_exact_python_version():
     import sys
     sVersion = ".".join(map(str, sys.version_info[:3]))
     sVersion = sVersion.strip()
     return sVersion

sys.version_info[:3] by itself gives a three-element tuple. Probably easier to use than the string version.

A couple alternatives:
sys.version[:5] or perhaps a bit safer -- sys.version.split()[0] both directly give you the string version. (Note this uses version not version_info.)

# 
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
# TO DO: RETURN TO THE LEFT OF FIRST "."
def get_python_version():
     sVersion = get_exact_python_version()
     return sVersion[0:1]

Probably unnecessary as a function.  A simple sVersion[0] in-line might be 
easier.

# 
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
# CHECK PYTHON VERSION, IF IT'S WRONG THEN GRACEFULLY EXIT BEFORE IT BLOWS UP
# (DAMN, PYTHON 2.x STILL COMPLAINS WITH SYNTAX ERRORS!!)
# MAYBE THIS COULD STILL BE USEFUL FOR CHECKING THE SUB-VERSION, IN THAT CASE
# TO DO: MORE GRANULAR CHECK, EG IF VERSION >= 3.5.0
def exit_if_wrong_python_version(sRightVersion):
     import os
     sCurrentVersion = get_python_version()
     if (sCurrentVersion != sRightVersion):
         print("" +
               "Wrong Python version (" +
               sCurrentVersion +
               "), this script should be run using Python " +
               sRightVersion +
               ".x. Exiting..."
               )
         os._exit(0)

Get used to Python string formatting...
print("Wrong Python version ({}), this script should be run using "
        "Python {}.x,  Exiting...".format(sCurrentVersion, sRightVersion))

Notice how I split the long single-line string into two shorter strings on two lines relying on the automatic string concatenation in Python. "string1 " "string2" becomes "string1 string2". Any whitespace (spaces, tabs, newlines) are ignored and the two strings are stuck together.

Also the common use is sys.exit() instead of os._exit().

# 
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
def get_script_filename():
     import os
     return os.path.basename(__file__)

sys.argv[0]

# 
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
def get_timestamp():
     import datetime
     return datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%d 
%H:%M:%S')

# 
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

def create_folder(sPath):
     import os
     import errno
     #if not os.path.exists(directory):
     #    os.makedirs(directory)
     try:
         os.makedirs(sPath, exist_ok=True)
     except OSError as exception:
         #if exception.errno != errno.EEXIST:
         print("ERROR #" + str(exception.errno) + "IN makedirs")
         raise

# 
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

def create_folders(sFolderPathTemplate:str="", iFromCount:int=1, 
iToCount:int=0, iCountWidth:int=0):
     # MAKE SURE TEMPLATE'S A STRING. OH, IS THIS NOT "PYTHONIC"? WELL IT'S 
MORE READABLE
     if is_string(sFolderPathTemplate) == False:
         iFromCount = 1; iToCount = 0;
More readable? The pythonic version would be simply to not use this at all. Now, which is more readable -- this crap or blank lines?

     sName = ""
     sCount = ""
This is not BASIC, you don't need to pre-declare your variables.

     iLoop = iFromCount
     while (iLoop <= iToCount) and (len(sFolderPathTemplate) > 0):
Why check for the template? It's a global variable, you know it's valid. If not, you deserve your errors.

         sCount = "{0}".format(iLoop)
         if (iCountWidth > 0):
             sCount = sCount.zfill(iCountWidth)
         sName = sFolderPathTemplate.replace("<iCount/>", sCount)
VERY tricky here, but...
           sCount = "{{:0{}}.format(iCountWidth)" if iCountWidth else "{}"
           sName = "{} {}".format(sFolderPathTemplate, sCount).format(iLoop)
More direct...
           if iCountWidth:
               fmt = "{{:0{}}}".format(iCountWidth)
               sCount = fmt.format(iLoop)
           else:
               sCount = str(iLoop)
           sName = "{} {}".format(sFolderPathTemplate, sCount)
Note this assumes the <iCount/> has been deleted from the template string as 
noted above.

         create_folder(sName)
         iLoop = iLoop + 1
More convenient and more pythonic:  iLoop += 1

############################################################################################################################################################
# MAIN LOGIC

def main():
     # 
----------------------------------------------------------------------------------------------------------------------------------------------------------------
     # MAKE SURE PYTHON VERSION IS CORRECT
     exit_if_wrong_python_version(sForPythonVersion)
     print("PYTHON VERSION (" + get_exact_python_version() + ") MATCHES REQUIRED VERSION 
(" + sForPythonVersion + ")")
     #print("get_python_version       returns \"" + get_python_version()       + 
"\"")
     #print("get_exact_python_version returns \"" + get_exact_python_version() + 
"\"")
Perhaps unnecessary to check the version, but YMMV... However, the exit_if_wrong_python_version() aborts with an error message, why bother to state that the version is good? If it isn't the program doesn't run anyway.

     # 
----------------------------------------------------------------------------------------------------------------------------------------------------------------
     # PRINT START TIMESTAMP
     print("" + get_timestamp() + " " + get_script_filename() + " STARTED.")

     # 
----------------------------------------------------------------------------------------------------------------------------------------------------------------
     # DO WHAT WE CAME TO DO
     # IT'S PROBABLY BAD FORM TO REFERENCE GLOBAL VARIABLES INSIDE THE SCOPE OF 
A FUNCTION?
     # BUT I WANT TO MAKE IT EASY TO CONFIGURE THE SCRIPT JUST BY CHANGING A 
COUPLE OF LINES
     # AT THE TOP, WITHOUT HAVING TO SEARCH THROUGH THE CODE
     create_folders(
         sFolderPathTemplate,
         iFromCount,
         iToCount,
         iCountWidth)
As you say, these are all global variables and are therefore already available to the create_folders() function, so why bother passing them as parameters? Your reason for globals here is probably valid, especially since they are used as constants rather than variables. But in general (in all programming languages) it is usually better and safer to avoid globals if possible.

     # 
----------------------------------------------------------------------------------------------------------------------------------------------------------------
     # NOW FINISH
     print("" + get_timestamp() + " " + get_script_filename() + " FINISHED.")
     #import os
     #os._exit(0)
Yes, your exit() is redundant and you are correct to comment it out.

But again I suggest that you get used to using print formatting, it is really 
versatile.

--
     -=- Larry -=-

--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to