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