Python on Linux:当列表未知时使用 If Elif Elif Elif 遍历列表

Python on Linux: Iterating through a list with If Elif Elif Elif when the list is unknown

我正在尝试制作一个 python 脚本,自动将文件从我的内部驱动器移动到任何插入的 USB 驱动器。但是这个目标路径是不可预测的,因为我不是每次都使用相同的 USB 驱动器.对于 Raspbian Buster 完整版,到目前为止我能做的最好的就是自动挂载到 /media/pi/xxxxx,其中 xxxxxx 部分是不可预测的。我正在尝试让我的脚本说明这一点。我可以通过

获得驱动器安装点
drives = os.listdir("/media/pi/")

但我担心有些会无效,因为在它们被拉出之前没有被卸载(我需要 运行 这个 w/o 显示器或键盘或 VNC 或任何用户输入其他而不是更换 USB 驱动器)。所以我认为我可能需要在 if elif elif elif 链中执行一系列 try catch 语句,以确保目标真正有效,但我不知道该怎么做 w/o 硬编码名称。我知道如何遍历一组我不知道的名称的唯一方法是

for candidate_drive in drives:

但我不知道如何让它进入下一个候选驱动器,只有当当前驱动器抛出异常时。

系统:Raspberry Pi4,Raspbian破坏力满,Python3.7.

旁注:我也在带有 usbmount 的 Buster lite 上尝试这个,它确实有可预测的安装名称,但我无法安装 exfat 和 ntfs,这是另一个 post 的问题。

更新:我考虑得更多,也许我需要尝试一下,except,else 语句,其中 except 是 pas,else 是 break?我正在尝试。

更新 2:我重新考虑了我的问题,也许我可以寻找成功的传输并在成功时打破循环,而不是寻找异常来确定何时尝试下一个可能的驱动器。

import os
import shutil

files_to_send = os.listdir("/home/outgoing_files/")
source_path = "/home/outgoing_files/" 
possible_USB_drives = os.listdir("/media/")

for a_possible_drive in possible_USB_drives:
    try:
        destpath = os.path.join("/media/", a_possible_drive)           
        for a_file in files_to_send:
            shutil.copy(source_path + a_file, destpath)
    except:
        pass # transfer to possible drive didn't work
    else:
        break # Stops this entire program bc the transfer worked!

如果你在一个目录的一侧有一个无符号数的目录,等等...你不能使用嵌套的 for cicles。你需要实现一个递归调用函数。如果您在一个目录中有多个目录,您想要查看所有目录,这可以使用相同的函数遍历目录列表,一遍又一遍地遍历它们,直到找到文件。

让我们看一个例子,你有一个像这样的路径结构:

path
    dir0
        dir2
            file3
    dir1
        file2
    file0
    file1

您现在无法知道需要多少 for cicles 来遍历此结构中的所有元素。您可以对单个目录的所有元素调用迭代 (for cicle),并对元素内的元素执行相同的操作。在这个结构中dirN其中N是一个数字表示一个目录,fileN表示一个文件。

您可以使用os.listdir()函数获取目录的内容:

print(os.listdir("path/")) 

returns:

['dir0', 'dir1', 'file0.txt', 'file1.txt']

将此函数与所有目录一起使用,您可以获得结构的所有元素。您只需要遍历所有 目录 。特别是目录,因为如果您使用文件:

print(os.listdir("path/file0.txt"))

你得到一个错误:

NotADirectoryError: [WinError 267]

但是,请记住 Python 中存在生成器表达式。

弦乐作品

如果您有一个 mainpath,您需要使用完整的字符串引用来访问其中的一个目录:"path/dirN"。您无法直接访问不在 .py 脚本范围内的文件:

print(os.listdir("dir0/"))

出现错误

FileNotFoundError: [WinError 3]

因此您需要始终使用实际路径格式化初始主路径,这样您可以访问结构的所有元素

过滤

我说过您可以使用生成器表达式递归地获取结构的目录。让我们看一个函数:

def searchfile(paths: list,search: str):
    for path in paths:
        print("Actual path: {}".format(path))

        contents = os.listdir(path)
        print("Contents: {}".format(contents))
   
        dirs = ["{}{}/".format(path,x) for x in contents if os.path.isdir("{}/{}/".format(path,x)) == True]
        print("Directories: {} \n".format(dirs))

        searchfile(dirs,search)

在这个函数中,我们使用 os.listdir() 获取实际路径的内容,然后使用生成器表达式对其进行过滤。显然,我们对实际路径的目录使用递归函数调用:searchfile(dirs,search)

这个算法可以应用于任何文件结构,因为path参数是一个列表。因此,您可以遍历包含目录的目录,以及包含更多目录的目录。

如果你想得到一个特定的文件,你可以使用第二个参数,search。你也可以实现一个条件并获取找到的文件的具体路径:

if search in contents:
    print("File found! \n")
    print("{}".format(os.path.abspath(search)))
    sys.exit()

希望对你有所帮助。