มีวิธีใน Python ในการแสดงรายการอักษรระบุไดรฟ์ที่ใช้งานอยู่ในระบบ Windows หรือไม่?
(Google-fu ของฉันดูเหมือนจะทำให้ฉันผิดหวังกับสิ่งนี้)
A C++
เทียบเท่า: การแจกแจงอักษรระบุไดรฟ์ที่มีอยู่ทั้งหมดใน Windows
มีวิธีใน Python ในการแสดงรายการอักษรระบุไดรฟ์ที่ใช้งานอยู่ในระบบ Windows หรือไม่?
(Google-fu ของฉันดูเหมือนจะทำให้ฉันผิดหวังกับสิ่งนี้)
A C++
เทียบเท่า: การแจกแจงอักษรระบุไดรฟ์ที่มีอยู่ทั้งหมดใน Windows
import win32api
drives = win32api.GetLogicalDriveStrings()
drives = drives.split('\000')[:-1]
print drives
ดัดแปลงมาจาก: http://www.faqts.com/knowledge_base/view.phtml/aid/4670
drives = [drivestr in drives.split('\000') if drivestr]
- person Wesley; 27.03.2010
pip install pypiwin32
ในฐานะผู้ดูแลระบบก่อนจึงจะสามารถใช้ import win32api
ได้
- person user42723; 11.08.2020
โดยไม่ต้องใช้ไลบรารีภายนอกใดๆ หากสิ่งนั้นสำคัญสำหรับคุณ:
import string
from ctypes import windll
def get_drives():
drives = []
bitmask = windll.kernel32.GetLogicalDrives()
for letter in string.uppercase:
if bitmask & 1:
drives.append(letter)
bitmask >>= 1
return drives
if __name__ == '__main__':
print get_drives() # On my PC, this prints ['A', 'C', 'D', 'F', 'H']
GetLogicalDrives()
เป็น Windows API แนวคิดของไดรฟ์แบบลอจิคัล (C:, D: ฯลฯ) ไม่มีอยู่บน Linux ฉันไม่รู้ว่า Eclipse กำลังทำอะไรอยู่
- person RichieHindle; 02.09.2013
พบวิธีแก้ปัญหานี้ใน Google ซึ่งดัดแปลงจากต้นฉบับเล็กน้อย ดูเหมือนเป็นงูหลามและไม่จำเป็นต้องนำเข้า "แปลกใหม่" ใด ๆ
import os, string
available_drives = ['%s:' % d for d in string.ascii_uppercase if os.path.exists('%s:' % d)]
ดูเหมือนคำตอบที่ดีกว่า นี่คือ cruft แฮ็กของฉัน
import os, re
re.findall(r"[A-Z]+:.*$",os.popen("mountvol /").read(),re.MULTILINE)
เจาะลึกคำตอบของ RichieHindle เล็กน้อย มันไม่ได้ดีกว่าจริงๆ แต่คุณสามารถทำให้ windows ทำงานขึ้นมาด้วยตัวอักษรของตัวอักษรจริงได้
>>> import ctypes
>>> buff_size = ctypes.windll.kernel32.GetLogicalDriveStringsW(0,None)
>>> buff = ctypes.create_string_buffer(buff_size*2)
>>> ctypes.windll.kernel32.GetLogicalDriveStringsW(buff_size,buff)
8
>>> filter(None, buff.raw.decode('utf-16-le').split(u'\0'))
[u'C:\\', u'D:\\']
mountvol /
ดูเหมือนจะไม่ทำอะไรนอกจากคายข้อมูลการใช้งานสำหรับคำสั่งบน Windows 7 หรือ 10...
- person ArtOfWarfare; 18.03.2018
Microsoft Script Repository ประกอบด้วย สูตรนี้ซึ่งอาจช่วยได้ ฉันไม่มีเครื่อง windows ที่จะทดสอบ แต่ฉันไม่แน่ใจว่าคุณต้องการ "ชื่อ", "ชื่อระบบ", "ชื่อโวลุ่ม" หรืออาจเป็นอย่างอื่น
import win32com.client
strComputer = "."
objWMIService = win32com.client.Dispatch("WbemScripting.SWbemLocator")
objSWbemServices = objWMIService.ConnectServer(strComputer,"root\cimv2")
colItems = objSWbemServices.ExecQuery("Select * from Win32_LogicalDisk")
for objItem in colItems:
print "Access: ", objItem.Access
print "Availability: ", objItem.Availability
print "Block Size: ", objItem.BlockSize
print "Caption: ", objItem.Caption
print "Compressed: ", objItem.Compressed
print "Config Manager Error Code: ", objItem.ConfigManagerErrorCode
print "Config Manager User Config: ", objItem.ConfigManagerUserConfig
print "Creation Class Name: ", objItem.CreationClassName
print "Description: ", objItem.Description
print "Device ID: ", objItem.DeviceID
print "Drive Type: ", objItem.DriveType
print "Error Cleared: ", objItem.ErrorCleared
print "Error Description: ", objItem.ErrorDescription
print "Error Methodology: ", objItem.ErrorMethodology
print "File System: ", objItem.FileSystem
print "Free Space: ", objItem.FreeSpace
print "Install Date: ", objItem.InstallDate
print "Last Error Code: ", objItem.LastErrorCode
print "Maximum Component Length: ", objItem.MaximumComponentLength
print "Media Type: ", objItem.MediaType
print "Name: ", objItem.Name
print "Number Of Blocks: ", objItem.NumberOfBlocks
print "PNP Device ID: ", objItem.PNPDeviceID
z = objItem.PowerManagementCapabilities
if z is None:
a = 1
else:
for x in z:
print "Power Management Capabilities: ", x
print "Power Management Supported: ", objItem.PowerManagementSupported
print "Provider Name: ", objItem.ProviderName
print "Purpose: ", objItem.Purpose
print "Quotas Disabled: ", objItem.QuotasDisabled
print "Quotas Incomplete: ", objItem.QuotasIncomplete
print "Quotas Rebuilding: ", objItem.QuotasRebuilding
print "Size: ", objItem.Size
print "Status: ", objItem.Status
print "Status Info: ", objItem.StatusInfo
print "Supports Disk Quotas: ", objItem.SupportsDiskQuotas
print "Supports File-Based Compression: ", objItem.SupportsFileBasedCompression
print "System Creation Class Name: ", objItem.SystemCreationClassName
print "System Name: ", objItem.SystemName
print "Volume Dirty: ", objItem.VolumeDirty
print "Volume Name: ", objItem.VolumeName
print "Volume Serial Number: ", objItem.VolumeSerialNumber
ฉันเขียนโค้ดชิ้นนี้:
import os
drives = [ chr(x) + ":" for x in range(65,91) if os.path.exists(chr(x) + ":") ]
ขึ้นอยู่กับคำตอบของ @ Barmaley แต่มีข้อดีของการไม่ใช้ string
โมดูลในกรณีที่คุณไม่ต้องการใช้ มันยังใช้ได้กับระบบของฉันด้วย ไม่เหมือนกับคำตอบของ @SingleNegationElimination
นี่เป็นอีกหนึ่งวิธีแก้ปัญหาที่ยอดเยี่ยมหากคุณต้องการแสดงรายการเฉพาะไดรฟ์บนแผ่นดิสก์ของคุณ ไม่ใช่ไดรฟ์เครือข่ายที่แมป หากคุณต้องการกรองตามคุณลักษณะที่แตกต่างกัน เพียงพิมพ์ drps
import psutil
drps = psutil.disk_partitions()
drives = [dp.device for dp in drps if dp.fstype == 'NTFS']
โซลูชันที่เหมาะสมที่สุดขึ้นอยู่กับ @RichieHindle
def get_drives():
drives = []
bitmask = windll.kernel32.GetLogicalDrives()
letter = ord('A')
while bitmask > 0:
if bitmask & 1:
drives.append(chr(letter) + ':\\')
bitmask >>= 1
letter += 1
return drives
บน Windows คุณสามารถทำ os.popen
import os
print os.popen("fsutil fsinfo drives").readlines()
นี่เป็นเวอร์ชันที่เรียบง่ายกว่า โดยไม่ต้องติดตั้งโมดูลเพิ่มเติมหรือฟังก์ชันใดๆ เนื่องจากอักษรระบุไดรฟ์ไม่สามารถไปเกิน A และ Z ได้ คุณจึงสามารถค้นหาได้ว่ามีเส้นทางสำหรับตัวอักษรแต่ละตัวหรือไม่ ดังตัวอย่างด้านล่าง:
>>> import os
>>> for drive_letter in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
if os.path.exists(f'{drive_letter}:'):
print(f'{drive_letter}:')
else:
pass
ซับเดียว:
>>> import os
>>> [f'{d}:' for d in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' if os.path.exists(f'{d}:')]
['C:', 'D:']
นี่คือแนวทางที่มีประสิทธิภาพสูงกว่าของฉัน (อาจสูงกว่านี้):
>>> from string import ascii_uppercase
>>> reverse_alphabet = ascii_uppercase[::-1]
>>> from ctypes import windll # Windows only
>>> GLD = windll.kernel32.GetLogicalDisk
>>> drives = ['%s:/'%reverse_alphabet[i] for i,v in enumerate(bin(GLD())[2:]) if v=='1']
ไม่มีใครใช้ฟีเจอร์เชิงประสิทธิภาพของ python จริงๆ ...
ใช่ ฉันไม่ได้ปฏิบัติตามแบบแผนเส้นทางมาตรฐานของ Windows ('\\')...
ตลอดหลายปีที่ผ่านมาของการใช้ python ฉันไม่มีปัญหากับ '/' ทุกที่ที่ใช้เส้นทางและได้ทำมันขึ้นมา มาตรฐานในโปรแกรมของฉัน
รหัสนี้จะส่งคืนรายการชื่อไดรฟ์และตัวอักษร เช่น:
['เกตเวย์(C:)', 'EOS_DIGITAL(L:)', 'คลังเพลง(O:)']
มันใช้เฉพาะไลบรารีมาตรฐานเท่านั้น มันต่อยอดจากแนวคิดบางอย่างที่ฉันพบข้างต้น windll.kernel32.GetVolumeInformationW() ส่งคืน 0 หากดิสก์ไดรฟ์ว่างเปล่า เช่น ซีดีรอมที่ไม่มีดิสก์ เป็นต้น รหัสนี้ไม่แสดงรายการไดรฟ์ว่างเหล่านี้
2 บรรทัดนี้จับตัวอักษรของไดรฟ์ทั้งหมด:
bitmask = (bin(windll.kernel32.GetLogicalDrives())[2:])[::-1] # strip off leading 0b and reverse
drive_letters = [ascii_uppercase[i] + ':/' for i, v in enumerate(bitmask) if v == '1']
นี่คือกิจวัตรฉบับเต็ม:
from ctypes import windll, create_unicode_buffer, c_wchar_p, sizeof
from string import ascii_uppercase
def get_win_drive_names():
volumeNameBuffer = create_unicode_buffer(1024)
fileSystemNameBuffer = create_unicode_buffer(1024)
serial_number = None
max_component_length = None
file_system_flags = None
drive_names = []
# Get the drive letters, then use the letters to get the drive names
bitmask = (bin(windll.kernel32.GetLogicalDrives())[2:])[::-1] # strip off leading 0b and reverse
drive_letters = [ascii_uppercase[i] + ':/' for i, v in enumerate(bitmask) if v == '1']
for d in drive_letters:
rc = windll.kernel32.GetVolumeInformationW(c_wchar_p(d), volumeNameBuffer, sizeof(volumeNameBuffer),
serial_number, max_component_length, file_system_flags,
fileSystemNameBuffer, sizeof(fileSystemNameBuffer))
if rc:
drive_names.append(f'{volumeNameBuffer.value}({d[:2]})') # disk_name(C:)
return drive_names
ซึ่งจะช่วยในการค้นหาไดรฟ์ที่ถูกต้องในระบบปฏิบัติการ Windows
import os
import string
drive = string.ascii_uppercase
valid_drives = []
for each_drive in drive:
if os.path.exist(each_drive+":\\"):
print(each_drive)
valid_drives.append(each_drive+":\\")
print(valid_drives)
ผลลัพธ์ที่ได้จะเป็น
C
D
E
['C:\\','D:\\','E:\\']
เนื่องจากฉันไม่ได้ติดตั้ง win32api บนโน้ตบุ๊กของฉัน ฉันจึงใช้โซลูชันนี้โดยใช้ wmic:
import subprocess
import string
#define alphabet
alphabet = []
for i in string.ascii_uppercase:
alphabet.append(i + ':')
#get letters that are mounted somewhere
mounted_letters = subprocess.Popen("wmic logicaldisk get name", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
#erase mounted letters from alphabet in nested loop
for line in mounted_letters.stdout.readlines():
if "Name" in line:
continue
for letter in alphabet:
if letter in line:
print 'Deleting letter %s from free alphabet %s' % letter
alphabet.pop(alphabet.index(letter))
print alphabet
หรือคุณสามารถรับความแตกต่างจากทั้งสองรายการเช่นโซลูชันที่ง่ายกว่านี้ (หลังจากเปิดตัวกระบวนการย่อย wmic เป็น mount_letters):
#get output to list
mounted_letters_list = []
for line in mounted_letters.stdout.readlines():
if "Name" in line:
continue
mounted_letters_list.append(line.strip())
rest = list(set(alphabet) - set(mounted_letters_list))
rest.sort()
print rest
วิธีแก้ปัญหาทั้งสองนั้นเร็วในทำนองเดียวกัน แต่ฉันเดาว่ารายการชุดจะดีกว่าด้วยเหตุผลบางอย่างใช่ไหม
ในฐานะส่วนหนึ่งของงานที่คล้ายกัน ฉันยังต้องคว้าอักษรระบุไดรฟ์ฟรีด้วย ฉันตัดสินใจว่าฉันต้องการจดหมายที่มีอยู่สูงสุด ขั้นแรกฉันเขียนมันออกมาตามสำนวนมากขึ้น จากนั้นจึงเขียนเป็น 1 ไลเนอร์เพื่อดูว่ามันยังสมเหตุสมผลอยู่หรือไม่ ฉันชอบชุดนี้มากเท่ากับความเข้าใจในรายการ: unused=set(alphabet)-set(used)
แทนที่จะต้องทำ unused = [a for a in aphabet if a not in used]
สิ่งที่เย็น!
def get_used_drive_letters():
drives = win32api.GetLogicalDriveStrings()
drives = drives.split('\000')[:-1]
letters = [d[0] for d in drives]
return letters
def get_unused_drive_letters():
alphabet = map(chr, range(ord('A'), ord('Z')+1))
used = get_used_drive_letters()
unused = list(set(alphabet)-set(used))
return unused
def get_highest_unused_drive_letter():
unused = get_unused_drive_letters()
highest = list(reversed(sorted(unused)))[0]
return highest
ซับหนึ่ง:
def get_drive():
highest = sorted(list(set(map(chr, range(ord('A'), ord('Z')+1))) -
set(win32api.GetLogicalDriveStrings().split(':\\\000')[:-1])))[-1]
ฉันยังเลือกตัวอักษรโดยใช้ map/range/ord/chr แทนการใช้ string เนื่องจากบางส่วนของสตริงเลิกใช้แล้ว
หากคุณไม่ต้องการกังวลเกี่ยวกับปัญหาข้ามแพลตฟอร์ม รวมถึงปัญหาข้ามแพลตฟอร์มหลาม เช่น Pypy และต้องการให้มีการใช้งานที่มีประสิทธิภาพอย่างเหมาะสมเมื่อมีการอัปเดตไดรฟ์ระหว่างรันไทม์:
>>> from os.path import exists
>>> from sys import platform
>>> drives = ''.join( l for l in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' if exists('%s:/'%l) ) if platform=='win32' else ''
>>> drives
'CZ'
นี่คือการทดสอบประสิทธิภาพของรหัสนี้:
4000 iterations; threshold of min + 250ns:
__________________________________________________________________________________________________________code___|_______min______|_______max______|_______avg______|_efficiency
⡇⠀⠀⢀⠀⠀⠀⠀⠀⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⣷⣷⣶⣼⣶⣴⣴⣤⣤⣧⣤⣤⣠⣠⣤⣤⣶⣤⣤⣄⣠⣦⣤⣠⣤⣤⣤⣤⣄⣠⣤⣠⣤⣤⣠⣤⣤⣤⣤⣤⣤⣄⣤⣤⣄⣤⣄⣤⣠⣀⣀⣤⣄⣤⢀⣀⢀⣠⣠⣀⣀⣤⣀⣠
drives = ''.join( l for l in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' if exists('%s:/'%l) ) if platform=='win32' else '' | 290.049ns | 1975.975ns | 349.911ns | 82.892%
หากคุณต้องการเฉพาะตัวอักษรสำหรับแต่ละไดรฟ์ คุณสามารถ:
from win32.win32api import GetLogicalDriveStrings
drives = [drive for drive in GetLogicalDriveStrings()[0]]