在 Python 中,如何检查驱动器是不是存在而不会为可移动驱动器抛出错误?

Posted

技术标签:

【中文标题】在 Python 中,如何检查驱动器是不是存在而不会为可移动驱动器抛出错误?【英文标题】:In Python, how do I check if a drive exists w/o throwing an error for removable drives?在 Python 中,如何检查驱动器是否存在而不会为可移动驱动器抛出错误? 【发布时间】:2011-05-10 10:54:30 【问题描述】:

这是我目前所拥有的:

import os.path as op
for d in map(chr, range(98, 123)): #drives b-z
    if not op.isdir(d + ':/'): continue

问题是它在Windows中弹出“无磁盘”错误框:

maya.exe - 没有磁盘:没有磁盘 驱动器。请插入磁盘 drive \Device\Harddisk1\DR1 [取消,再试一次,继续]

我无法捕获异常,因为它实际上并没有引发 Python 错误。

显然,这只发生在分配了一个字母但没有插入驱动器的可移动驱动器上。

有没有办法在不明确告诉脚本跳过哪个驱动器的情况下解决这个问题?

在我的场景中,我在学校实验室,驱动器号会根据我所在的实验室计算机而变化。另外,我访问磁盘管理的安全权限为零。

【问题讨论】:

顺便说一下,避免使用地图:[chr(c) for c in xrange(98, 123)]。说 xrange(ord('b'), ord('z'))` 也可以说更清楚。另外,不要跳过“A”;没有人说它必须是软盘驱动器。我总是禁用未使用的软盘控制器,从而释放 A:. 很棒的提示!我刚才用你描述的 ord() 方法实现了它。效果很好! 我只是注意到我必须输入 ord('z') + 1 才能将其一直运行到 z 【参考方案1】:

使用ctypes 包访问GetLogicalDrives 函数。这不需要外部库,例如 pywin32,因此它是可移植的,尽管使用起来有点笨拙。例如:

import ctypes
import itertools
import os
import string
import platform

def get_available_drives():
    if 'Windows' not in platform.system():
        return []
    drive_bitmask = ctypes.cdll.kernel32.GetLogicalDrives()
    return list(itertools.compress(string.ascii_uppercase,
               map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1])))

itertools.compress 在 Python 2.7 和 3.1 中添加;如果您需要支持

def compress(data, selectors):
    for d, s in zip(data, selectors):
        if s:
            yield d

【讨论】:

啊,你是圣人!不过不要忘记import platform。此外,它仍在返回没有插入驱动器的可移动驱动器。这实际上是这里的问题是我无法检测驱动器是否已加载磁盘或没有某种错误。 更新——春季学期本周开始,我有机会在学校进行测试。一切都很好,没有打嗝,但我需要在更多的机器上尝试,然后才能看到它是否真的能在没有弹出窗口的情况下工作。【参考方案2】:

这是一种适用于 Windows 和 Linux 的方法,适用于 Python 2 和 3:

import platform,os
def hasdrive(letter):
    return "Windows" in platform.system() and os.system("vol %s: 2>nul>nul" % (letter)) == 0

【讨论】:

Ummm...我在那里看不到与 linux 有任何关系。 尽管如此,这实际上对我的需求非常有帮助。你碰巧知道一种抑制命令外壳弹出的方法吗? @sfjedi:请参阅我的回答 (***.com/questions/4188326/…),了解在不弹出命令外壳的情况下执行此操作的方法。 Matt Joiner:函数 hasdrive 也适用于 Linux(返回 False,因为 Linux 没有驱动器号) 我希望获得一些关于 "os.system("vol %s: 2>nul>nul" % (letter)) == 0" 实际作用的信息。我很难弄清楚。【参考方案3】:

如果你有win32file模块,你可以调用GetLogicalDrives():

def does_drive_exist(letter):
    import win32file
    return (win32file.GetLogicalDrives() >> (ord(letter.upper()) - 65) & 1) != 0

【讨论】:

我喜欢这种方法;不过,我正在寻找一种跨平台的方法,因为我的脚本可能会通过 Windows/Mac/Linux 在 Maya 上运行。 @sfjedi,我很想知道 Maya 如何在 Linux 上模拟驱动器号 :) 好电话。我还没有为 Linux 开发过任何东西,但我只是觉得走上 Windows 特有的道路并不自在。我知道 Maya 可以在 Linux 上运行,这就是我比较担心的原因。不过,你提出了一个很好的观点。我还需要更多地考虑 Linux 上的目录结构。实际上,我专门尝试识别插入根目录中的“学校”文件夹的任何闪存驱动器。这就是这个脚本的实际目的。 顺便说一句,我喜欢你如何超越并回答真正的问题。 这不适用于不同平台的所有操作系统【参考方案4】:

要禁用错误弹出,您需要使用 pywin 设置SEM_FAILCRITICALERRORS Windows 错误标志:

old_mode = win32api.SetErrorMode(0)
SEM_FAILCRITICALERRORS = 1 # not provided by PyWin, last I checked
win32api.SetErrorMode(old_mode & 1)

这告诉 Win32 不显示重试对话框;发生错误时,立即返回给应用程序。

请注意,这是 Python 调用 应该 做的事情。原则上,Python 应该为你设置这个标志。不幸的是,由于 Python 可能嵌入到另一个程序中,它不能像那样更改进程范围的标志,并且 Win32 无法以仅影响 Python 而不会影响其余代码的方式指定此标志。

【讨论】:

不幸的是,虽然我在 Windows 7 上对此进行了测试,但我正在尝试使此脚本跨平台。另外,win32api 似乎需要不同的构建,具体取决于您拥有的处理器类型,我必须安装这些构建中的每一个,以使其兼容。我错了吗?【参考方案5】:
import os

possible_drives_list = [chr(97 + num).upper() for num in range(26)]

for drive in possible_drives_list:
    print(drive + ' exists :' + str(os.path.exists(drive + ':\\')))

【讨论】:

【参考方案6】:
import os 
def IsDriveExists(drive):
    return os.path.exists(drive + ':\\')
    
print(IsDriveExists('c')) 
print(IsDriveExists('d'))
print(IsDriveExists('e'))
print(IsDriveExists('x'))
print(IsDriveExists('v'))

这适用于任何操作系统

【讨论】:

你是个传奇。谢谢!更多pythonic。【参考方案7】:

只要可以接受一点解析,这是一种无需安装 win32api 且无需遍历所有可能的驱动器号的方法。

from subprocess import check_output
def getDriveLetters():
    args = [
        'wmic',
        'logicaldisk',
        'get',
        'caption,description,providername',
        '/format:csv'
    ]
    output = check_output(args)
    results = list()
    for line in  output.split('\n'):
        if line:
            lineSplit = line.split(',')
            if len(lineSplit) == 4 and lineSplit[1][1] == ':':
                results.append(lineSplit[1][0])
    return results

您还可以通过添加and lineSplit[2] == 'Network Connection' 来解析特定驱动器类型,例如“网络连接”以获取所有网络安装驱动器号的列表。

或者,您可以返回一个字典,而不是返回一个列表,其中键是驱动器号,值是 unc 路径 (lineSplit[3])。或者您想从wmic 获取的任何其他信息。查看更多选项:wmic logicaldisk get /?

【讨论】:

以上是关于在 Python 中,如何检查驱动器是不是存在而不会为可移动驱动器抛出错误?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查文件夹是不是存在于垃圾箱中或不在谷歌驱动器中?

如何检查MongoDB本机nodejs驱动程序中是不是存在集合?

检查 IPC 消息队列是不是已经存在而不创建它

安卓;检查文件是不是存在而不创建新文件

DataTable update() 插入重复的新行而不检查它是不是存在

如何从 C# 或 Javascript 检查文件是不是存在?