Home > OS >  Simplify multiple try and except statements
Simplify multiple try and except statements

Time:10-02

What my function does:

  1. creates a war file by processing the folder contents (/tmp/A, /tmp/B and so on)
  2. Does some file path and folder path manipulations to get the final version from the war file.
  3. store the file name in one variable and the version in another.
  4. Push the war file to the Repository using curl.

I'm using multiple try & except blocks to catch the exception for each action and looks very un-pythonic.

Is there an elegant and simple way to approach this ? thanks in advance.

import shutil
import traceback
import subprocess
import os
import glob


def my_function(path_a, path_b, tmp_dir)

    try:
        <shutil.copy to the tmp dir>
    except:
        traceback.print_exc()

    try:
        war_process = subprocess.run([WAR GENERATION COMMAND], check=True,  stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        print(war_process.stdout.decode("utf-8"))
    except subprocess.CalledProcessError as e:
        exit_code = e.returncode
        stderror = e.stderr
        print(exit_code, stderror)
        print(war_process.stderr.decode("utf-8"))

    try:
        output_folder = os.path.join("/tmp/dir/work", FILE_PATH, ARTIFACT_DATE, FILE_WO_EXTENSION)
    except:
        traceback.print_exc()
    try:
        file_name = list(glob.glob(os.path.join(output_folder, "*.war")))
    except:
        traceback.print_exc()
    try:
        file_path = os.path.join(output_folder, file_name)
    except:
        traceback.print_exc()
    try:
        os.rename(file_path, file_path.split('war')[0]   ".tgz")
    except:
        traceback.print_exc()

    try:
        file_version = os.path.basename(file_path)
    except:
        traceback.print_exc()

    cmd = "curl -u username -T ....)"

    try:
        curl_output = subprocess.run([cmd], shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        print(curl_output.stdout.decode("utf-8"))
    except subprocess.CalledProcessError as er:
        print(proc_c.stderr.decode("utf-8"))
        exit_c = er.returncode
        std = er.stderr
        print(exit_c, std)

CodePudding user response:

You can write try once, then handle all the exceptions later:

try:
    output_folder = os.path.join("/tmp/dir/work", FILE_PATH, ARTIFACT_DATE, FILE_WO_EXTENSION)
    file_name = list(glob.glob(os.path.join(output_folder, "*.war")))
    file_path = os.path.join(output_folder, file_name)
    os.rename(file_path, file_path.split('war')[0]   ".tgz")
except FooException:
    print('foo')
except BarException:
    print('bar')

CodePudding user response:

First of all never use bare except in your code. Read bullets 6 to 11 in PEP8:Programming Recommendations.

My suggestion is to use this code instead:

def my_function(path_a, path_b, tmp_dir)

    try:
        <shutil.copy to the tmp dir>
    except:
        traceback.print_exc()

    try:
        war_process = subprocess.run([WAR GENERATION COMMAND], check=True,  stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        print(war_process.stdout.decode("utf-8"))
        output_folder = os.path.join("/tmp/dir/work", FILE_PATH, ARTIFACT_DATE, FILE_WO_EXTENSION)
        file_name = list(glob.glob(os.path.join(output_folder, "*.war")))
        file_path = os.path.join(output_folder, file_name)
        os.rename(file_path, file_path.split('war')[0]   ".tgz")
        file_version = os.path.basename(file_path)
    except subprocess.CalledProcessError as e:
        exit_code = e.returncode
        stderror = e.stderr
        print(exit_code, stderror)
        print(war_process.stderr.decode("utf-8"))
    except Exception as e:
        print(f'The program caught an exception {e}')
        traceback.print_exc()

    cmd = "curl -u username -T ....)"

    try:
        curl_output = subprocess.run([cmd], shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        print(curl_output.stdout.decode("utf-8"))
    except subprocess.CalledProcessError as er:
        print(proc_c.stderr.decode("utf-8"))
        exit_c = er.returncode
        std = er.stderr
        print(exit_c, std)

The second and the third try/except blocks must stay separated because both catch the same exception.

Also, if any of the blocks you created here catch a specific exception in this list, you should behave them like you behave the subprocess.CalledProcessError .

Best practice is to write one try block with multiple excepts in which each except block catches a specific exception.

CodePudding user response:

You don't need to put a try/except block after every statement. It would be better to put multiple statements in a try/except block

def my_function(path_a, path_b, tmp_dir)

    try:
        <shutil.copy to the tmp dir>
        war_process = subprocess.run([WAR GENERATION COMMAND], check=True,  stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        print(war_process.stdout.decode("utf-8"))
    except subprocess.CalledProcessError as e:
        exit_code = e.returncode
        stderror = e.stderr
        print(exit_code, stderror)
        print(war_process.stderr.decode("utf-8"))

    try:
        output_folder = os.path.join("/tmp/dir/work", FILE_PATH, ARTIFACT_DATE, FILE_WO_EXTENSION)
        file_name = list(glob.glob(os.path.join(output_folder, "*.war")))
        file_path = os.path.join(output_folder, file_name)
        os.rename(file_path, file_path.split('war')[0]   ".tgz")
        file_version = os.path.basename(file_path)
    except:
        traceback.print_exc()

    cmd = "curl -u username -T ....)"

    try:
        curl_output = subprocess.run([cmd], shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        print(curl_output.stdout.decode("utf-8"))
    except subprocess.CalledProcessError as er:
        print(proc_c.stderr.decode("utf-8"))
        exit_c = er.returncode
        std = er.stderr
        print(exit_c, std)
```
  • Related