Zanurkuj w Pythonie/Praca z katalogami: Różnice pomiędzy wersjami

Usunięta treść Dodana treść
zamiana {{Nawigacja|Python|->{{Nawigacja|Zanurkuj w Pythonie| [[Python/->[[../
Piotr (dyskusja | edycje)
poprawki
Linia 1:
== 6.5. Praca z katalogami ==
{{Podświetl|py}}
== 6.5. Praca z katalogami ==
 
Moduł <tt>os.path</tt> zawiera kilka funkcji służących do manipulacji plikami i katalogami. Przyjrzymy się teraz obsłudze ścieżek i odczytywaniu zawartości katalogów.
 
Moduł <ttcode>os.path</ttcode> zawiera kilka funkcji służących do manipulacji plikami i katalogami (w systemie Windows nazywanymi folderami). Przyjrzymy się teraz obsłudze ścieżek i odczytywaniu zawartości katalogów.
'''Przykład 6.16. Tworzenie ścieżek do plików'''
 
{{Python/Przykład
'''Przykład |6.16. |Tworzenie ścieżek do plików'''
|tekst=
>>> import os
>>> os.path.join("c:\\music\\ap\\", "mahadeva.mp3") #(1) (2)
{{samp|'c:\\music\\ap\\mahadeva.mp3'}}
>>> os.path.join("c:\\music\\ap", "mahadeva.mp3") #(3)
{{samp|'c:\\music\\ap\\mahadeva.mp3'}}
>>> os.path.expanduser("~") #(4)
{{samp|'c:\\Documents and Settings\\mpilgrim\\My Documents'}}
>>> os.path.join(os.path.expanduser("~"), "Python") #(5)
{{samp|'c:\\Documents and Settings\\mpilgrim\\My Documents\\Python'}}
 
# <ttcode>os.path</ttcode> jest odwołaniemreferencją do modułu, (jakiegoa --ten moduł zależy od platformy z jakiej korzystasz)korzystamy. Tak jak [[../Obsługa wyjątków#przy-6.2|<ttcode>getpass</ttcode>]] niweluje różnice między platformami ustawiając <ttcode>getpass</ttcode> na funkcję odpowiednią dla Twojegonaszego systemu, tak <ttcode>os</ttcode> ustawia <ttcode>path</ttcode> na moduł specyficzny dla konkretnej platformy.
# Funkcja <ttcode>join</ttcode> modułu <ttcode>os.path</ttcode> tworzy ścieżkę dostępu do pliku z jednej lub kilku ścieżek częściowych. W tym przypadku po prostu łączy dwa stringiłańcuchy znaków. (ZauważZauważmy, że w Windowsie musiszmusimy używać podwójnych ukośników.)
# W tym, trochę bardziej skomplikowanym, przypadku, <ttcode>join</ttcode> dopisze dodatkowy ukośnik do ścieżki przed dołączeniem do niej nazwy pliku. ByłemNie bardzomusimy szczęśliwy,pisać gdymałej togłupiej odkryłem, bofunkcji <ttcode>addSlashIfNecessary</ttcode> było jedną z najgłupszych małych funkcji, które musiałem napisać zaczynając programować w nowym języku. Nie pisz tej głupiej funkcji w Pythonie,ponieważ mądrzy ludzie zrobili to już to za Ciebienas.
# <ttcode>expanduser</ttcode> rozwninierozwinie w ścieżce znak <ttcode>~</ttcode> na ścieżkę katalogu domowego aktualnie zalogowanego użytkownika. Ta funkcja działa w każdym systemie, w którym użytkownicy mają swoje katalogi domowe, między innymi w systemach Windows, UNIX i Mac OS X;, nic nie robiale w systemie Mac OS nie otrzymujemy żadnych efektów.
# Używając tych technik, możeszmożemy łatwo tworzyć ścieżki do plików i katalogów wewnątrz katalogu domowego.
}}
 
'''Przykład 6.17. Rozdzielanie ścieżek'''
 
{{Python/Przykład
'''Przykład |6.17. |Rozdzielanie ścieżek'''
|tekst=
>>> os.path.split("c:\\music\\ap\\mahadeva.mp3") #(1)
{{samp|('c:\\music\\ap', 'mahadeva.mp3')}}
>>> (filepath, filename) = os.path.split("c:\\music\\ap\\mahadeva.mp3") #(2)
>>> filepath #(3)
{{samp|'c:\\music\\ap'}}
>>> filename #(4)
{{samp|'mahadeva.mp3'}}
>>> (shortname, extension) = os.path.splitext(filename) #(5)
>>> shortname
{{samp|'mahadeva'}}
>>> extension
{{samp|'.mp3'}}
# Funkcja <tt>split</tt> dzieli pełną ścieżkę i zwraca krotkę zawierającą ścieżkę do katalogu i nazwę pliku. Pamiętasz, jak mówiłem, że można używać przypisania wielu zmiennych do zwracania kilku wartości z funkcji? <tt>split</tt> jest taką właśnie funkcją.
# Przypisujesz wynik działania funkcji <tt>split</tt> krotce dwóch zmiennych. Każda zmienna będzie teraz zawierać wartość odpowiedniego elementu krotki zwróconej przez funkcję <tt>split</tt>.
# Pierwsza zmienna, <tt>filepath</tt>, zawiera pierwszy element krotki - ścieżkę pliku.
# Druga zmienna, <tt>filename</tt>, zawiera drugi element krotki - nazwę pliku.
# Moduł <tt>os.path</tt> zawiera też funkcję <tt>splitext</tt>, która zwraca krotkę zawierającą właściwą nazwę pliku i jego rozszerzenie. Używasz tej samej techniki, co poprzednio, do przypisania każdej części do osobnej zmiennej.
 
# Funkcja <ttcode>split</ttcode> dzieli pełną ścieżkę i zwraca krotkęlistę, która zawierającązawiera ścieżkę do katalogu i nazwę pliku. Pamiętasz, jak mówiłemmówiliśmy, że można używać przypisania wielu[[../Deklarowanie zmiennych#Wielozmienne przypisania|wielozmiennego przypisania]] do zwracania kilku wartości z funkcji? <ttcode>split</ttcode> jest taką właśnie funkcją.
'''Przykład 6.18. Wyświetlanie zawartości katalogu'''
# Przypisujesz wynik działania funkcji <ttcode>split</ttcode> krotcedo krotki dwóch zmiennych. Każda zmienna będzie teraz zawierać wartość odpowiedniego elementu krotki zwróconej przez funkcję <ttcode>split</ttcode>.
# Pierwsza zmienna, <ttcode>filepath</ttcode>, zawiera pierwszy element krotkizwróconej listy -- ścieżkę pliku.
# Druga zmienna, <ttcode>filename</ttcode>, zawiera drugi element krotkilisty -- nazwę pliku.
# Moduł <ttcode>os.path</ttcode> zawiera też funkcję <ttcode>splitext</ttcode>, która zwraca krotkę zawierającą właściwą nazwę pliku i jego rozszerzenie. UżywaszUżywamy tej samej techniki, co poprzednio, do przypisania każdej części do osobnej zmiennej.
}}
 
{{Python/Przykład
'''Przykład |6.18. |Wyświetlanie zawartości katalogu'''
|tekst=
>>> os.listdir("c:\\music\\_singles\\") #(1)
{{samp|['a_time_long_forgotten_con.mp3', 'hellraiser.mp3',
'kairo.mp3', 'long_way_home1.mp3', 'sidewinder.mp3',
'spinning.mp3']}}
>>> dirname = "c:\\"
>>> os.listdir(dirname) #(2)
{{samp|['AUTOEXEC.BAT', 'boot.ini', 'CONFIG.SYS', 'cygwin',
'docbook', 'Documents and Settings', 'Incoming', 'Inetpub', 'IO.SYS',
'MSDOS.SYS', 'Music', 'NTDETECT.COM', 'ntldr', 'pagefile.sys',
'Program Files', 'Python20', 'RECYCLER',
'System Volume Information', 'TEMP', 'WINNT']}}
>>> [f for f in os.listdir(dirname)
... if os.path.isfile(os.path.join(dirname, f))] #(3)
{{samp|['AUTOEXEC.BAT', 'boot.ini', 'CONFIG.SYS', 'IO.SYS', 'MSDOS.SYS',
'NTDETECT.COM', 'ntldr', 'pagefile.sys']}}
>>> [f for f in os.listdir(dirname)
... if os.path.isdir(os.path.join(dirname, f))] #(4)
{{samp|['cygwin', 'docbook', 'Documents and Settings', 'Incoming',
'Inetpub', 'Music', 'Program Files', 'Python20', 'RECYCLER',
'System Volume Information', 'TEMP', 'WINNT']}}
 
# Funkcja <ttcode>listdir</ttcode> pobiera ścieżkę do katalogu i zwraca listę jego zawartości.
# <ttcode>listdir</ttcode> zwraca zarówno pliki jak i katalogi, bez wskazania które są którymi.
# MożeszMożemy użyć [[../Filtrowanie listy|filtrowania listy]] i funkcji <ttcode>isfile</ttcode> modułu <ttcode>os.path</ttcode>, aby oddzielić pliki od katalogów. <ttcode>isfile</ttcode> pobieraprzyjmuje ścieżkę do pliku i zwraca <ttcode>1True</ttcode>, jeśli reprezentuje ona plik albo <ttcode>0False</ttcode> w innym przypadku. W przykładzie używamy <ttcode>os.path.join</ttcode>, aby uzyskać pełną ścieżkę, ale <ttcode>isfile</ttcode> pracuje też z częściowymize ścieżkami względnymi wobec bieżącego katalogu. MożeszMożemy użyć <ttcode>os.getcwd()</ttcode> aby pobrać bieżący katalog.
# <ttcode>os.path</ttcode> zawiera też funkcję <ttcode>isdir</ttcode>, zwracającąktóra zwraca <ttcode>1True</ttcode>, jeśli ścieżka reprezentuje katalog i <ttcode>0False</ttcode> w innym przypadku. MożeszMożemy jej użyć do uzyskania listy podkatalogów.
}}
 
{{Python/Przykład
'''Przykład |6.19. |Listowanie zawartości katalogu w <tt>{{Python/Src|fileinfo.py</tt>'''}}
|tekst=
<nowiki>def listDirectory(directory, fileExtList):
u"zwraca listę obiektów zawierających metadane dla plików o podanych rozszerzeniach"
fileList = [os.path.normcase(f) for f in os.listdir(directory)] #(1) (2)
fileList = [os.path.join(directory, f) for f in fileList
if os.path.splitext(f)[1] in fileExtList] #(3) (4) (5)</nowiki>
 
# <ttcode>os.listdir(directory)</ttcode> zwraca listę wszystkich plików i podkatalogów w katalogu <ttcode>directory</ttcode>.
def listDirectory(directory, fileExtList):
# Iterując po liście z użyciem zmiennej <ttcode>f</ttcode>, wykorzystujemy <ttcode>os.path.normcase(f)</ttcode>, aby znormalizować wielkość liter zgodnie z domyślnymdomyślną wielkością liter w systemem operacyjnym. Funkcja <ttcode>normcase</ttcode> jest użyteczną, prostą funkcją, która stanowi równoważnik pomiędzy systemami operacyjnymi, w których wielkość liter w nazwie pliku nie ma znaczenia, w którym np. <tt class="lang-none">mahadeva.mp3</tt> i <tt class="lang-none">mahadeva.MP3</tt> są takimi samymi plikami. Na przykład w Windowsie i Mac OS, <ttcode>normcase</ttcode> będzie konwertował całą nazwę pliku na małe litery, a w systemach kompatybilnych z UNIX-em funkcja ta będzie zwracała niezmienioną nazwę pliku.
"get list of file info objects for files of particular extensions"
# Iterując ponownie po liście z użyciem <ttcode>f</ttcode>, wykorzystujemy <ttcode>os.path.splitext(f)</ttcode>, aby podzielić nazwę pliku na nazwę i jej rozszerzenie.
fileList = [os.path.normcase(f)
# Dla każdego pliku sprawdzamy, czy rozszerzenie jest w liście plików, o które nam chodzi (czyli <ttcode>fileExtList</ttcode>, która została przekazana do <ttcode>listDirectory</ttcode>).
for f in os.listdir(directory)] #(1) (2)
# Dla każdego pliku, który nas interesuje, wykorzystujemy <ttcode>os.path.join(directory, f)</ttcode>, aby skonstruować pełną ścieżkę pliku i zwrócić listę zawierającą pełne ścieżki.
fileList = [os.path.join(directory, f)
}}
for f in fileList
if os.path.splitext(f)[1] in fileExtList] #(3) (4) (5)
 
# <tt>os.listdir(directory)</tt> zwraca listę wszystkich plików i podkatalogów w katalogu <tt>directory</tt>.
# Iterując po liście z użyciem zmiennej <tt>f</tt>, wykorzystujemy <tt>os.path.normcase(f)</tt>, aby znormalizować wielkość liter zgodnie z domyślnym systemem operacyjnym. Funkcja <tt>normcase</tt> jest użyteczną, prostą funkcją, która stanowi równoważnik pomiędzy systemami operacyjnymi, w których wielkość liter w nazwie pliku nie ma znaczenia, w którym np. <tt class="lang-none">mahadeva.mp3</tt> i <tt class="lang-none">mahadeva.MP3</tt> są takimi samymi plikami. Na przykład w Windowsie i Mac OS, <tt>normcase</tt> będzie konwertował całą nazwę pliku na małe litery, w systemach kompatybilnych z UNIX-em funkcja ta będzie zwracała niezmienioną nazwę pliku.
# Iterując ponownie po liście z użyciem <tt>f</tt>, wykorzystujemy <tt>os.path.splitext(f)</tt>, aby podzielić nazwę pliku na nazwę i jej rozszerzenie.
# Dla każdego pliku sprawdzamy, czy rozszerzenie jest w liście plików, o które nam chodzi (czyli <tt>fileExtList</tt>, która została przekazana do <tt>listDirectory</tt>).
# Dla każdego pliku, który nas interesuje, wykorzystujemy <tt>os.path.join(directory, f)</tt>, aby skonstruować pełną ścieżkę pliku i zwrócić listę zawierającą pełne ścieżki.
 
{{Infobox|
JeślliJeśli to możliwe, powinieneśpowinniśmy używaćkorzystać z funkcji zw modułówmodułach <ttcode>os</ttcode> i <ttcode>os.path</ttcode> do manipulacji plikami, katalogami i ścieżkami. Te moduły opakowują moduły specyficzne dla konkretnego systemu, więc funkcje takie, jak <ttcode>os.path.split</ttcode> pooprawnie działają w systemach UNIX, Windows, Mac OS i we wszystkich innych systemach wspieranych przez Pythona.
}}
 
Jest jeszcze jednainna metoda dostania się do zawartości katalogu. JestMetoda ta jest bardzo potężna i używa zestawu symboli wieloznacznych (ang. ''wildcard''), z którymi mogłeśmożna się spotkać pracując w linii komendpoleceń.
 
{{Python/Przykład
'''Przykład |6.20. |Listowanie zawartości katalogu przy pomocy <ttcode>glob</ttcode>'''
|tekst=
 
>>> os.listdir("c:\\music\\_singles\\") #(1)
{{samp|['a_time_long_forgotten_con.mp3', 'hellraiser.mp3',
'kairo.mp3', 'long_way_home1.mp3', 'sidewinder.mp3',
'spinning.mp3']}}
>>> import glob
>>> glob.glob('c:\\music\\_singles\\*.mp3') #(2)
{{samp|['c:\\music\\_singles\\a_time_long_forgotten_con.mp3',
'c:\\music\\_singles\\hellraiser.mp3',
'c:\\music\\_singles\\kairo.mp3',
'c:\\music\\_singles\\long_way_home1.mp3',
'c:\\music\\_singles\\sidewinder.mp3',
'c:\\music\\_singles\\spinning.mp3']}}
>>> glob.glob('c:\\music\\_singles\\s*.mp3') #(3)
{{samp|['c:\\music\\_singles\\sidewinder.mp3',
'c:\\music\\_singles\\spinning.mp3']}}
>>> glob.glob('c:\\music\\*\\*.mp3') #(4)
 
# Jak wcześniej powiedzieliśmy, <ttcode>os.listdir</ttcode> pobiera ścieżkę do katalogu i zwraca wszystkie pliki i podkatalogi, które się w nim znajdują.
# Z drugiej strony, moduł <ttcode>glob</ttcode> na podstawie podanego wyrażenia (ang.składającego się z symboli ''wildcard'')wieloznacznych, zwraca pełne ścieżki wszystkich plików, które spełniają te wyrażenie. Tutaj wyrażenie jest ścieżką do katalogu plus <code>"*.mp3"</code>, który będzie dopasowywał wszystkie pliki <tt class="lang-none">.mp3</tt>. Dodajmy, że każdy element zwracanej listy jest już pełną ścieżką do pliku.
# Jeśli chceszchcemy znaleźć wszystkie pliki w określonym katalogu, gdzie nazwa zaczyna się od <code>"s"</code>, a kończy na <tt>".mp3"</tt>, możeszmożemy to zrobić w ten sposób.
# Teraz rozważ taki scenariusz: mamy katalog z muzyką z kilkoma podkatalogami, wewnątrz których są pliki <tt class="lang-none">.mp3</tt>. Możemy pobrać listę wszystkich tych plików za pomocą jednego wywołania <ttcode>glob</ttcode>, wykorzystując połączenie dwóch wyrażeń. Pierwszym jest <tt>"*.mp3"</tt> (wyszukuje pliki .mp3), a drugim są same w sobie ścieżki do katalogów, aby przetworzyć każdy podkatalog w <tt class="lang-none">c:\music</tt>. Ta prosto wyglądająca funkcja daje nam niesamowite możliwości!
}}
 
<noinclude>
{{Nawigacja|Zanurkuj w Pythonie|
[[../Korzystanie_z_sys.modules|Korzystanie z <ttcode>sys.modules</ttcode>]]|
[[../Wyjątki_i_operacje_na_plikach_-_wszystko_razem|Wszystko razem]]|
}}
{{Podświetl|py}}
</noinclude>