Organize if else block Background
I have a code that basically caches file. The way it works is it will first check if the file exists on the local drive and if it does if there is a flag passed called validate_file_size then it will do another check to see if the size of the file on local drive equals the size of the file on S3. if they equal we assume the local file is the most recent version and if they don't then we need to download the latest version.
CODE
  def cache_file(self, s3_path_of_file: str, local_path: Path, file_name: str, validate_file_size: bool = True) -&gt; None:
        bucket, key = s3.deconstruct_s3_url(f&quot;{s3_path_of_file}/{file_name}&quot;)
        is_file_size_valid = True
        if not (local_path / file_name).exists():
            os.makedirs(local_path, exist_ok=True)
            try:
                s3_client().download_file(bucket, key, f&quot;{local_path}/{file_name}&quot;)
                os.chmod(local_path / file_name, S_IREAD | S_IRGRP | S_IROTH)
            except botocore.exceptions.ClientError as e:
                if e.response[&quot;Error&quot;][&quot;Code&quot;] == &quot;404&quot;:
                    raise FileNotFoundError
        elif validate_file_size:
            is_file_size_valid = self._is_file_size_equal(
                s3_path_of_file, local_path, file_name
            )
            if not is_file_size_valid:
                try:
                    s3_client().download_file(bucket, key, f&quot;{local_path}/{file_name}&quot;)
                    os.chmod(local_path / file_name, S_IREAD | S_IRGRP | S_IROTH)
                except botocore.exceptions.ClientError as e:
                    if e.response[&quot;Error&quot;][&quot;Code&quot;] == &quot;404&quot;:
                        raise FileNotFoundError
            else:
                logger.info(&quot;Cached File is Valid!&quot;)

ISSUE
I am wondering if there is a better way to organize my if else statements so my code is cleaner and less redundant. I am not particularly happy about this block in particular that is repeated twice.
 try:
     s3_client().download_file(bucket, key, f&quot;{local_path}/{file_name}&quot;)
     os.chmod(local_path / file_name, S_IREAD | S_IRGRP | S_IROTH)
 except botocore.exceptions.ClientError as e:
     if e.response[&quot;Error&quot;][&quot;Code&quot;] == &quot;404&quot;:
         raise FileNotFoundError

One obvious choice is to take it out as a separate function but I am almost wondering if i can avoid that and organize my if else statement in a way where i don't really repeat this try except block twice.
I'm not a Python programmer, but the way to not repeat the code without creating a function is to do the download checking first have flags set by that checking one for creating a new file path and one for doing the download. Figure out everything that needs to be done first and then do the download and path creation as necessary.
pseudo code:
if not local path or file:
    create_local_path_flag = True

if file size not valid:
    file_out_of_date_flag = True

if create_local_path_flag or file_out_of_date_flag:
    if create_local_path_flag:
        create_local_path()
    download_file()