windows 在 Python 中,如何检查驱动器是否存在而不会引发可移动驱动器的错误?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4188326/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 15:36:37  来源:igfitidea点击:

In Python, how do I check if a drive exists w/o throwing an error for removable drives?

pythonwindowserror-handlingpathdisk

提问by jedmao

Here's what I have so far:

这是我到目前为止所拥有的:

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

The problem is that it pops up a "No Disk" error box in Windows:

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

maya.exe - No Disk: There is no disk in the drive. Please insert a disk into drive \Device\Harddisk1\DR1 [Cancel, Try Again, Continue]

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

I can't catch the exception because it doesn't actually throw a Python error.

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

Apparently, this only happens on removable drives where there is a letter assigned, but no drive inserted.

显然,这仅发生在分配了字母但未插入驱动器的可移动驱动器上。

Is there a way to get around this issue without specifically telling the script which drives to skip?

有没有办法解决这个问题,而无需特别告诉脚本要跳过哪些驱动器?

In my scenario, I'm at the school labs where the drive letters change depending on which lab computer I'm at. Also, I have zero security privileges to access disk management.

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

采纳答案by Adam Rosenfield

Use the ctypespackage to access the GetLogicalDrivesfunction. This does not require external libraries such as pywin32, so it's portable, although it is a little clunkier to work with. For example:

使用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.compresswas added in Python 2.7 and 3.1; if you need to support <2.7 or <3.1, here's an implementation of that function:

itertools.compress在 Python 2.7 和 3.1 中添加;如果您需要支持 <2.7 或 <3.1,这是该功能的实现:

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

回答by Frédéric Hamidi

If you have the win32filemodule, you can call GetLogicalDrives():

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

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

回答by Alexander

Here's a way that works both on Windows and Linux, for both Python 2 and 3:

这是一种适用于 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

回答by Glenn Maynard

To disable the error popup, you need to set the SEM_FAILCRITICALERRORSWindows error flag using pywin:

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

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

This tells Win32 not to show the retry dialog; when an error happens, it's returned to the application immediately.

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

Note that this is what Python calls are supposedto do. In principle, Python should be setting this flag for you. Unfortunately, since Python may be embedded in another program, it can't change process-wide flags like that, and Win32 has no way to specify this flag in a way that only affects Python and not the rest of the code.

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

回答by PolyMesh

As long as a little parsing is acceptable, this is one way to do it without installing win32api and without iterating through all possible drive letters.

只要稍微解析是可以接受的,这是一种无需安装 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

You could also parse for specific drive types, such as "Network Connection" to get a list of all network mounted drive letters by adding and lineSplit[2] == 'Network Connection'for example.

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

Alternatively, rather than returning a list, you could return a dictionary, where keys are drive letters and values are unc paths (lineSplit[3]). Or whatever other info you want to pull from wmic. To see more options: wmic logicaldisk get /?

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