多次调用同一函数的最佳实践是什么

2024-10-02 16:31:08 发布

您现在位置:Python中文网/ 问答频道 /正文

我是Python新手,我正在尝试编写一些东西,可以获取位于不同目录中的文件并解压缩它们(*.Z文件)。我正在尝试理解在不重复下面代码的情况下执行此操作的最佳方法。但是,除了为每个文件再次添加同一行之外,是否可以为每个文件名以某种方式循环该行?例如,一个文件可能位于/root/xxx/yyy.Z中,另一个文件位于/root/xxx/zzz.Z和/root/xxx/aaa.Z中

我可以使用指向每个目录的参数来运行这个函数,但这感觉很笨拙,但仍然有效

def UnzipFiles(pathtofile1,pathtofile2,pathtofile3):
    for filename in os.listdir(pathtofile1):
        if filename.endswith(".Z"): 
           retcode = subprocess.call(['gunzip', pathtofile1])
    else:
        if retcode != 0:
            raise IOError('unzipfiles exited with code %d' % retcode)

    for filename in os.listdir(pathtofile2):
        if filename.endswith(".Z"): 
           retcode = subprocess.call(['gunzip', pathtofile1])
    else:
        if retcode != 0:
            raise IOError('unzipfiles exited with code %d' % retcode)

    for filename in os.listdir(pathtofile3):
        if filename.endswith(".Z"): 
           retcode = subprocess.call(['gunzip', pathtofile3])
    else:
        if retcode != 0:
            raise IOError('unzipfiles exited with code %d' % retcode)

我必须澄清一些我在最初的帖子中没有提到的事情。(1) .Z文件组是它们自己的目录,例如一组文件位于/root/xxx/yyy.Z中,另一组文件位于/root/yyy/zzz.Z和/root/aaa/aaa.Z中。所以我需要循环浏览三个不同的目录。(2)大约有20个左右的文件正在解压缩。这项活动最多每月进行一次


Tags: 文件in目录forifosrootfilename
3条回答

把它变成一个函数似乎为时过早,因为它的硬编码只能处理3个“文件”参数,即使修改为一个参数,它仍然绑定到".Z"扩展名。这使得它基本上只适用于一个超特定的任务:使用特定的扩展名解压确切地3个文件(真正的目录…)

此外,目录和文件路径之间似乎存在混淆os.listdir拉入目录中的所有文件,这似乎与您命名变量的方式相反,这表明您正在传递文件路径

无论哪种方式,您都可以删除函数中的多个块并将根文件夹传递给路径,或者相反,跳过os.listdir并为subprocess.call提供一个直接的单路径

我建议内联编写代码:

for path in os.listdir('/root/xxx/'):
    if path.endswith('.Z') and ret := subprocess.call(['gunzip', path]):
        raise IOError(f'gunzip exited with code {ret} on {path}')

如果您真的经常这样做,以致对呼叫方来说太混乱,您可以使用:

def unzip_all(directory, extension='.Z'):
    for path in os.listdir(directory):
        if path.endswith(extension) and ret := subprocess.call(['gunzip', path]):
            raise IOError(f'gunzip exited with code {ret} on {path}')

如果您只想提取3个特定文件,而不是3个特定目录:

for path in ['root/xxx/foo.Z', 'root/xxx/bar.Z', 'root/xxx/baz.Z']:
    if ret := subprocess.call(['gunzip', path]):
        raise IOError(f'gunzip exited with code {ret} on {path}')

由于gunzip接受多个参数,您可以利用这一点将整个过程归结为:

paths = ['root/xxx/foo.Z', 'root/xxx/bar.Z', 'root/xxx/baz.Z']

if ret := subprocess.call(['gunzip'] + paths):
    raise IOError(f'gunzip exited with code {ret} on {paths}')

注意,这使用了Python 3.8中的胡须分配语法:=

顺便说一句

else:
    if:
        ....

是一种更复杂的写作方式

elif:
    ....

我建议:;函数应该是lower_camel_caseUpperCamelCase是为类保留的

可以在python中使用zip函数同时迭代3个变量

def UnzipFiles(pathtofile1,pathtofile2,pathtofile3):
    for filename1,filename2,filename3 in zip(os.listdir(pathtofile1),os.listdir(pathtofile2),os.listdir(pathtofile3)):
        if filename1.endswith(".Z"): 
            retcode1 = subprocess.call(['gunzip', pathtofile1])
        else:
            if retcode1 != 0:
               raise IOError('unzipfiles exited with code %d' % retcode1)
        if filename2.endswith(".Z"): 
            retcode2 = subprocess.call(['gunzip', pathtofile2])
        else:
            if retcode2 != 0:
               raise IOError('unzipfiles exited with code %d' % retcode2)
        if filename3.endswith(".Z"): 
            retcode3 = subprocess.call(['gunzip', pathtofile3])
        else:
           if retcode3 != 0:
               raise IOError('unzipfiles exited with code %d' % retcode3)

这基本上是一样的

只需更改1个输入文件的代码并选中os walk(),然后就可以使用map()传递文件列表

results = list(map(UnzipFiles, [list of files]))

相关问题 更多 >