2013-03-06 22 views
11

Su Windows 7 con Python 2.7 come posso rilevare se un percorso è un collegamento simbolico? Questo non funziona , dice che restituisce false se false o non supportate e il percorso che sto fornendo è sicuramente un collegamento simbolico quindi presumo che non sia supportato su Windows? Cosa posso fare?os.path.islink su windows con python

+3

[Questo] (http://bugs.python.org/issue13143) può provid e un po 'di aiuto. – crayzeewulf

+2

dare un'occhiata al pacchetto ['jaraco.windows'] (https://bitbucket.org/jaraco/jaraco.windows/src/default/jaraco/windows/filesystem/__init__.py); deve usare 'ctypes' per supportare questo. Python 3.2 * fa * supporta correttamente i collegamenti simbolici di Windows. –

risposta

19

Il problema principale è che si sta utilizzando una versione vecchia di Python. Se si desidera attenersi a 2.x, non sarà in grado di sfruttare le nuove funzionalità aggiunte dopo l'inizio del 2010.

Una di queste funzionalità è la gestione dei collegamenti simbolici NTFS. Tale funzionalità è stata aggiunta in 3,2 alla fine del 2010. (Vedere la 3.2, 3.1 e 2.7 sorgente per i dettagli.)

Il motivo Python non ha gestito i collegamenti simbolici NTFS prima di allora è che non vi era nulla di simile fino alla fine del 2009. (IIRC, il supporto è stato incluso nel kernel 6.0, ma il supporto per l'utente richiede un service pack su Vista/2008, solo 7/2008R2 e successivi sono integrati. Inoltre, è necessario un MSVCRT nuovo-sufficiente per poter accedere a tale supporto per l'utente e Python ha una politica esplicita di non eseguire l'aggiornamento a nuove versioni di Visual Studio all'interno di una versione secondaria.

Il motivo per cui il codice non è stato riportato su 2.x è that there will never be a 2.8 e versioni di correzioni di errori come 2.7. 3 (o 2.7.4) non ottengono ne w caratteristiche, solo correzioni di bug.

Questo è stato segnalato come issue 13143 e la correzione prevista è modificare i documenti 2.7 per chiarire che islink restituisce sempre False su Windows.

Quindi, se si desidera leggere i collegamenti simbolici NTFS in Windows, eseguire l'aggiornamento a Python 3.2+ oppure utilizzare win32api, ctypes, ecc. Per farlo da soli.

Oppure, come suggerisce Martijn Pieters, invece di farlo da solo, utilizzare una libreria di terze parti come jaraco.windows che lo fa e/o prendere in prestito their code.

Oppure, se lo si desidera, prendere in prestito il codice dal sorgente 3.2 e creare un modulo di estensione C attorno ad esso. Se si rintraccia da ntpath a os a nt (che in realtà è posixmodule.c), credo che il coraggio di esso sia in win32_xstat_impl and win32_xstat_impl_w.

+0

Chi ha downvoted, si preoccupa di spiegare perché? – abarnert

+0

fantastico! grazie abarnert – user391986

+0

Devi essere disinformato. i punti di analisi esistono da Windows NT 5 (Windows 2000) con NTFS 3.0. Ed era funzionale. l'implementazione di Python è semplicemente pigra o anche disinformata. –

5

Questo è quello che ho finito per usare per determinare se un file o una directory è un collegamento in Windows 7:

def isLink(path): 
    if os.path.exists(path): 
     if os.path.isdir(path): 
      FILE_ATTRIBUTE_REPARSE_POINT = 0x0400 
      attributes = ctypes.windll.kernel32.GetFileAttributesW(unicode(path)) 
      return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) > 0 
     else: 
      command = ['dir', path] 
      try: 
       with open(os.devnull, 'w') as NULL_FILE: 
        o0 = check_output(command, stderr=NULL_FILE, shell=True) 
      except CalledProcessError as e: 
       print e.output 
       return False 
      o1 = [s.strip() for s in o0.split('\n')] 
      if len(o1) < 6: 
       return False 
      else: 
       return 'SYMLINK' in o1[5] 
    else: 
     return False 

EDIT: Modificato il codice come da suggerimenti di Zitrax e Annan

+0

Vale la pena prendere 'CalledProcessError's da' check_output' quando il file non esiste. Puoi anche passare 'stderr = subprocess.PIPE' per nascondere l'output di errore che va allo stdin. Questa soluzione è davvero hacky, ma più funzionale rispetto all'altra risposta. – Annan

+0

Questa risposta non funziona per verificare se una directory è un collegamento, seno il comando dir sarà solo elencare il contenuto. – Zitrax

+0

@Zitrax: 'dir/al" percorso * "' funziona –

5

per le directory :

import os, ctypes 
def IsSymlink(path): 
    FILE_ATTRIBUTE_REPARSE_POINT = 0x0400 
    return os.path.isdir(path) and (ctypes.windll.kernel32.GetFileAttributesW(unicode(path)) & FILE_ATTRIBUTE_REPARSE_POINT): 

Source

+0

la fonte è morta – thatsIch

+0

@thatsIch ha aggiornato il collegamento alla cache di archive.org. – Zitrax

+0

confrontando la fonte manca la dichiarazione di ritorno. Puoi verificare se il risultato è> 0 altrimenti il ​​risultato è 1024 – thatsIch