3
\$\begingroup\$

The code below uses a single command line 'filename' argument to create a batch and python skeleton script file in the cwd. The python file is then automatically opened in IDLE for convenience.

As a beginner making a significant amount of python files for worked educational examples this could save me 15 minutes per day.

Example usage for the below code which is named "make.py":

  1. Cd in command line to the desired wd
  2. Input script name("make") and the desired name of the files to be created minus any filename extension(in this case "test") as the single argument

Batch file created("test.bat"):

@py.exe C:\Users\Dave\Desktop\2016Coding\AutomateBoring\18-GUIAutomation\test.py %*
@pause

Python file("test.py") created in cwd and which is opened automatically in IDLE:

#! python3

#

import logging

logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - " +\
            "%(levelname)s - %(message)s")

def main():
    pass

if __name__ == "__main__":
    main()

Code:

#! python3

# Takes a command line filename and creates a batch file and .py file
# named "filename" in the cwd. The python file contains a basic script
# framework. In additon, the python file will be automatically opened.


import argparse
import os
import subprocess


def handle_input():
    """Parses user commandline input"""

    parser = argparse.ArgumentParser()
    parser.add_argument("filename", type=str,
                        help="The name of the files to create minus any" +\
                        "extensions.")
    args = parser.parse_args()
    return args.filename


def make_batch(filename: str, cwd: str):
    """Makes a batch file name "filename" in "cwd"""

    filepath = os.path.join(cwd, filename + ".bat")
    with open(filepath, "w") as f:
        f.write("@py.exe " + os.path.join(cwd, filename + ".py ") +
                "%*\n@pause")
    print("\nCreated batch file: {}".format(filepath))


def make_py(filepath: str):
    """Makes a .py file in cwd written with a basic skelton script"""

    # *****I realize it's a simpler task to copy a template from a .
    # py file created for the purpose and write that to the new .py*****

    shebang = "#! python3\n\n"
    comment = "#\n\n"
    imports = "import logging\n\n"
    logging = "logging.basicConfig(level=logging.DEBUG, format=\"%(asctime)s - " \
              "\" +\\\n\t\t    \"%(levelname)s - %(message)s\")\n\n"
    functions = "def main():\n\tpass\n\n"
    main = "if __name__ == \"__main__\":\n\tmain()"

    with open(filepath, "w") as f:
        f.write(shebang + comment + imports + logging + functions + main)
    print("Created .py file: {}".format(filepath))


def open_py_idle(filename: str):
    """Opens a .py file in IDLE using subprocess"""

    idle_path = r"C:\Users\Dave\AppData\Local\Programs\Python\Python35" +\
                r"-32\Lib\idlelib\idle.bat"
    subprocess.run([idle_path, filename], shell=True)


def main():
    """Creates .bat and .py file in cwd. Auto opens .py file"""

    filename = handle_input()
    cwd = os.getcwd()
    python_file = os.path.join(cwd, filename + ".py")

    # ensure an existing python file is not overwritten
    if not os.path.exists(python_file):
        # make .bat file named "filename" in cwd
        make_batch(filename, cwd)
        # make .py file
        make_py(python_file)
        # open .py file in idle
        open_py_idle(python_file)
    else:
        print("\n.py file already exists: {}".format(python_file))

    print("\n*****Done*****\n")



if __name__ == "__main__":
    main()
\$\endgroup\$
  • \$\begingroup\$ Please do not update the code in your question to incorporate feedback from answers, doing so goes against the Question + Answer style of Code Review. This is not a forum where you should keep the most updated version in your question. Please see what you may and may not do after receiving answers. \$\endgroup\$ – Simon Forsberg Dec 13 '16 at 17:50
4
\$\begingroup\$

This is rather good code: no blatant style issues, doctrings for functions and some comments (albeit some are unnecessary). Well done.

Now for the critics:

  • traditional shebang would rather look like #!/usr/bin/python3 or #!/usr/bin/env python3;
  • the comments you put between the shebang and the imports should be the module docstring instead;
  • use 4 spaces per indentation level rather than tabs;
  • since you are creating files in the current working directory, you can check for file existence with the filename only; thus you can do it early and generate an argparse error instead of "rolling your own" ;
  • you could make the path to idle an optional parameter of the CLI instead of hardcoding your path to it;
  • I like to use the file argument of the print function to visualize the layout of the output file better. But for the python template, using a multiline string should be an improvement:
#!/usr/bin/env python3

"""Takes a command line filename and creates a batch file and .py file
named "filename" in the cwd. The python file contains a basic script
framework. In additon, the python file will be automatically opened.
"""

import argparse
import os
import subprocess


PYTHON_TEMPLATE = '''\
#!/usr/bin/env python3

"""DOCSTRING"""


import logging


logging.basicConfig(
    level=logging.DEBUG,
    format="%(asctime)s - %(levelname)s - %(message)s")


def main():
    pass


if __name__ == "__main__" :
    main()'''


def handle_input():
    """Parses user commandline input"""

    parser = argparse.ArgumentParser()
    parser.add_argument(
            'filename',
            help='The name of the files to '
                 'create minus any extensions.')
    parser.add_argument(
            '-i', '--idle-path',
            help='The path to the IDLE executable',
            default=r'C:\Users\Dave\AppData\Local\Programs'
                    r'\Python\Python35-32\Lib\idlelib\idle.bat')
    args = parser.parse_args()

    filename = args.filename
    # ensure an existing python file is not overwritten
    if os.path.exists(filename+'.py'):
        parser.error('file already exist: {}.py'.format(filename))
    return filename, args.idle_path


def make_batch(filename: str, cwd: str):
    """Makes a batch file name "filename" in "cwd"""

    filepath = os.path.join(cwd, filename + ".bat")
    with open(filepath, "w") as f:
        print('@py.exe', os.path.join(cwd, filename+'.py'), '%*', file=f)
        print('@pause', file=f)
    print('Created batch file:', filepath)


def make_py(filepath: str):
    """Makes a .py file in cwd written with a basic skelton script"""

    # *****I realize it's a simpler task to copy a template from a .
    # py file created for the purpose and write that to the new .py*****

    with open(filepath, "w") as f:
        print(PYTHON_TEMPLATE, file=f)
    print('Created .py file:', filepath)


def open_py_idle(filename: str, idle_path: str):
    """Opens a .py file in IDLE using subprocess"""

    subprocess.run([idle_path, filename], shell=True)


def main():
    """Creates .bat and .py file in cwd. Auto opens .py file"""

    filename, idle_path = handle_input()
    cwd = os.getcwd()
    python_file = os.path.join(cwd, filename + '.py')

    make_batch(filename, cwd)
    make_py(python_file)
    open_py_idle(python_file, idle_path)

    print('\n*****Done*****\n')


if __name__ == "__main__":
    main()
\$\endgroup\$

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.