2013-03-06 21 views
11

W Windows 7 z Pythonem 2.7 jak mogę wykryć, czy ścieżka jest dowiązaniem symbolicznym? To nie działa , mówi, że zwraca wartość false, jeśli jest false lub nie jest obsługiwane, a ścieżka, którą podaję, jest z pewnością dowiązaniem symbolicznym, więc zakładam, że nie jest obsługiwana w oknach? Co mogę zrobić?os.path.islink w oknach z pytonem

+3

[W] (http://bugs.python.org/issue13143) może dostarczając e trochę pomocy. – crayzeewulf

+2

spójrz na pakiet '' jaraco.windows' (https://bitbucket.org/jaraco/jaraco.windows/src/default/jaraco/windows/filesystem/__init__.py); musi używać "ctypes", aby to wspierać. Python 3.2 * poprawnie obsługuje dowiązania symboliczne Windows. –

Odpowiedz

19

Głównym problemem jest to, że używasz zbyt starej wersji Pythona. Jeśli chcesz pozostać przy 2.x, nie będziesz mógł skorzystać z nowych funkcji dodanych po roku 2010.

Jedną z tych funkcji jest obsługa dowiązań symbolicznych NTFS. Że funkcjonalność została dodana w 3.2 pod koniec 2010 roku (patrz źródło informacji 3.2, 3.1 i 2.7.)

Powodem Python nie obsługiwać dowiązania NTFS wcześniej jest to, że nie było czegoś takiego, dopiero pod koniec 2009 roku. (IIRC, wsparcie zostało uwzględnione w jądrze 6.0, ale obsługa użytkowników wymaga dodatku Service Pack w systemie Vista/2008, tylko 7/2008R2 i nowsze są dostarczane z wbudowanym. Dodatkowo, potrzebujesz nowego MSVCRT, który będzie w stanie uzyskać dostęp do tego wsparcie dla użytkowników, a Python ma jawną politykę nie aktualizowania do nowych wersji programu Visual Studio w ramach niewielkiego wydania).

Powód, dla którego kod nie został przeniesiony z powrotem do wersji 2.x to that there will never be a 2.8, oraz poprawki błędów, takie jak 2.7. 3 (lub 2.7.4) nie dostaniesz w funkcje, tylko poprawki błędów.

ta została zgłoszona jako issue 13143, a poprawka jest przeznaczona do zmiany 2,7 ​​docs wyjaśnić, że islink zawsze zwraca False w systemie Windows.

Jeśli chcesz przeczytać dowiązania symboliczne NTFS pod Windows, albo uaktualnij do Python 3.2+, albo musisz użyć win32api, ctypes itd., Aby zrobić to sam.

Lub, jak sugeruje Martijn Pieters, zamiast robić to sam, użyj biblioteki innej firmy, takiej jak jaraco.windows, która to robi i/lub pożycza their code.

Lub, jeśli naprawdę chcesz, pożyczyć kod ze źródła 3.2 i zbudować moduł rozszerzenia C wokół niego. Jeśli prześledzisz od ntpath do os do nt (co jest faktycznie posixmodule.c), uważam, że jego wnętrzności są w win32_xstat_impl and win32_xstat_impl_w.

+0

Ktokolwiek potępił, chciałby wyjaśnić, dlaczego? – abarnert

+0

niesamowite! dziękuję abarnert – user391986

+0

Musisz być źle poinformowany. punkty ponownej analizy istnieją z Windows NT 5 (Windows 2000) z NTFS 3.0. I to było funkcjonalne. implementacja Pythona jest po prostu leniwą lub wprowadzoną w błąd. –

5

To, co skończyło się w celu ustalenia, czy plik lub katalog jest ogniwem w systemie 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: Zmodyfikowany kod zgodnie z sugestiami Zitrax i Annana

+0

Warto przyłapać 'CalledProcessError's z' check_output', gdy plik nie istnieje. Możesz także przekazać 'stderr = subprocess.PIPE', aby ukryć wyjście błędów idące na standardowe wejście. To rozwiązanie jest naprawdę hacky, ale bardziej funkcjonalne niż druga odpowiedź. – Annan

+0

Ta odpowiedź nie działa w celu sprawdzenia, czy katalog jest linkiem, a po prostu polecenie dir wyświetli zawartość. – Zitrax

+0

@Zitrax: 'dir/al" path * "' works –

5

dla katalogów :

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

źródło jest martwe – thatsIch

+0

@thatsIch zaktualizowany link do archiwum cache. – Zitrax

+0

porównując źródło brakuje instrukcji return. Możesz sprawdzić, czy wynik jest> 0, czy wynik jest 1024 – thatsIch