【问题标题】:Python on Linux: Iterating through a list with If Elif Elif Elif when the list is unknownLinux 上的 Python:当列表未知时,使用 If Elif Elif Elif 遍历列表
【发布时间】:2020-07-20 03:24:18
【问题描述】:

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

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

但我担心有些会因为在被拉出之前没有被卸载而无效(我需要在没有显示器、键盘或 VNC 或任何用户输入的情况下运行此程序,而不是更换 USB 驱动器)。所以我认为我可能需要在 if elif elif elif 链中执行一系列 try catch 语句,以确保目的地确实有效,但我不知道如何在没有硬编码的情况下做到这一点中的名称。我知道如何遍历一组我不知道的名称的唯一方法是

for candidate_drive in drives:

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

系统:Raspberry Pi 4、Raspbian buster full、Python 3.7。

旁注:我也在 Buster lite w/usbmount 上尝试此操作,它确实具有可预测的安装名称,但我无法安装 exfat 和 ntfs,这是另一个帖子的问题。

更新:我在考虑这个问题,也许我需要一个 try, 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!

【问题讨论】:

  • 我不熟悉您遇到的 USB 问题,但这听起来像是生成器功能可能会有所帮助。
  • 我使用 else 块来打破 for 循环似乎有效。

标签: python linux usb shutil libusb


【解决方案1】:

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

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

path
    dir0
        dir2
            file3
    dir1
        file2
    file0
    file1

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

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

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

返回:

['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()

希望对你有所帮助。

【讨论】:

  • 谢谢!我需要一段时间才能慢慢理解这一点,并且很高兴学习;看起来很有希望。我对非常密集的dirs= 线有点困惑。
猜你喜欢
  • 2017-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-17
  • 2012-09-22
  • 2017-07-03
  • 2022-11-23
  • 1970-01-01
相关资源
最近更新 更多