Get started learning Python with DataCamp's free Intro to Python tutorial. Learn Data Science by completing interactive coding challenges and watching videos by expert instructors. Start Now!
This site is generously supported by DataCamp. DataCamp offers online interactive Python Tutorials for Data Science. Join 11 million other learners and get started learning Python for data science today!
Good news! You can save 25% off your Datacamp annual subscription with the code LEARNPYTHON23ALE25 - Click here to redeem your discount
Moduły i pakiety
W programowaniu moduł to część oprogramowania mająca określona funkcjonalność. Na przykład, podczas tworzenia gry w ping ponga, jeden moduł może być odpowiedzialny za logikę gry, a inny moduł rysuje grę na ekranie. Każdy moduł składa się z innego pliku, który może być edytowany osobno.
Pisanie modułów
Moduły w Pythonie to po prostu pliki Pythonowe z rozszerzeniem .py. Nazwa modułu jest taka sama jak nazwa pliku. Pythonowy moduł może posiadać zestaw funkcji, klas, czy zmiennych zdefiniowanych i zaimplementowanych. Powyższy przykład obejmuje dwa pliki:
mygame/
-
mygame/game.py
-
mygame/draw.py
Skrypt Pythona game.py
implementuje grę. Używa funkcji draw_game
z pliku draw.py
,
czyli inaczej mówiąc modułu draw
, który implementuje logikę rysowania gry na ekranie.
Moduły są importowane z innych modułów przy użyciu polecenia import
. W tym przypadku skrypt game.py
może wyglądać tak:
# game.py
# importujemy moduł draw
import draw
def play_game():
...
def main():
result = play_game()
draw.draw_game(result)
# to oznacza, że jeśli ten skrypt zostanie uruchomiony, to
# main() zostanie wykonana
if __name__ == '__main__':
main()
Moduł draw
może wyglądać w ten sposób:
# draw.py
def draw_game():
...
def clear_screen(screen):
...
W tym przypadku moduł game
importuje moduł draw
, co umożliwia używanie funkcji zaimplementowanych
w tym module. Funkcja main
używa lokalnej funkcji play_game
do uruchomienia gry, a następnie
rysuje wynik gry używając funkcji zaimplementowanej w module draw
o nazwie draw_game
. Aby użyć
funkcji draw_game
z modułu draw
, musimy określić w którym module funkcja jest
zaimplementowana, używając operatora kropki. Aby odwołać się do funkcji draw_game
z modułu game
,
musimy zaimportować moduł draw
, a następnie wywołać draw.draw_game()
.
Gdy dyrektywa import draw
jest uruchamiana, interpreter Python szuka pliku w katalogu, w którym skrypt był uruchamiany z nazwą modułu i sufiksem .py
. W tym przypadku będzie szukał draw.py
. Jeśli zostanie odnaleziony, zostanie zaimportowany. Jeśli nie zostanie odnaleziony, kontynuuje poszukiwania wśród modułów wbudowanych.
Możliwe, że zauważyłeś, że przy importowaniu modułu, tworzony jest plik .pyc
. To jest skompilowany plik Pythona.
Python kompiluje pliki do bajtkodu Pythona, aby nie musiał analizować plików za każdym razem, gdy moduły są ładowane. Jeśli istnieje plik .pyc
, zostaje załadowany zamiast pliku .py
. Proces ten jest przejrzysty dla użytkownika.
Importowanie obiektów modułu do obecnej przestrzeni nazw
Przestrzeń nazw to system w którym każdy obiekt jest nazwany i może być dostępny w Pythonie. Importujemy funkcję draw_game
do przestrzeni nazw głównego skryptu używając polecenia from
.
# game.py
# importujemy moduł draw
from draw import draw_game
def main():
result = play_game()
draw_game(result)
Możliwe, że zauważyłeś, że w tym przykładzie, nazwa modułu nie poprzedza draw_game
, ponieważ określiliśmy nazwę modułu używając polecenia import
.
Zaletą tej notacji jest to, że nie musisz za każdym razem odnosić się do modułu. Jednak, przestrzeń nazw nie może mieć dwóch obiektów o tej samej nazwie, więc polecenie import
może zastąpić istniejący obiekt w przestrzeni nazw.
Importowanie wszystkich obiektów z modułu
Możesz użyć polecenia import *
do zaimportowania wszystkich obiektów w module w ten sposób:
# game.py
# importujemy moduł draw
from draw import *
def main():
result = play_game()
draw_game(result)
To może być nieco ryzykowne, ponieważ zmiany w module mogą wpływać na moduł, który go importuje, ale jest to krótsze i nie wymaga od Ciebie specyfikowania każdego obiektu, który chcesz zaimportować z modułu.
Niestandardowa nazwa importu
Moduły mogą być ładowane pod dowolną nazwą, którą chcesz. Jest to przydatne, gdy importujesz moduł warunkowo, aby użyć tej samej nazwy w reszcie kodu.
Na przykład, jeśli masz dwa moduły draw
z nieco innymi nazwami, możesz zrobić to w ten sposób:
# game.py
# importujemy moduł draw
if visual_mode:
# w trybie wizualnym rysujemy używając grafiki
import draw_visual as draw
else:
# w trybie tekstowym wypisujemy tekst
import draw_textual as draw
def main():
result = play_game()
# to może być wizualne lub tekstowe w zależności od visual_mode
draw.draw_game(result)
Inicjalizacja modułu
Gdy moduł jest ładowany do działającego skryptu Pythona po raz pierwszy, jest inicjalizowany przez wykonanie kodu w module raz. Jeśli inny moduł w Twoim kodzie ponownie importuje ten sam moduł, nie zostanie on załadowany ponownie, więc lokalne zmienne wewnątrz modułu działają jako "singleton", co oznacza, że są inicjalizowane tylko raz.
Możesz wtedy użyć tego do inicjalizacji obiektów. Na przykład:
# draw.py
def draw_game():
# przy czyszczeniu ekranu możemy użyć głównego obiektu ekranu inicjalizowanego w tym module
clear_screen(main_screen)
...
def clear_screen(screen):
...
class Screen():
...
# inicjalizujemy main_screen jako singleton
main_screen = Screen()
Rozszerzanie ścieżki ładowania modułu
Istnieje kilka sposobów, aby powiedzieć interpreterowi Pythona, gdzie szukać modułów, poza
domyślnym lokalnym katalogiem i modułami wbudowanymi. Możesz użyć zmiennej środowiskowej PYTHONPATH
, aby określić dodatkowe katalogi, w których szukać modułów w ten sposób:
PYTHONPATH=/foo python game.py
To wykonuje game.py
, i umożliwia skryptowi ładowanie modułów z katalogu foo
, jak i
z katalogu lokalnego.
Możesz również użyć funkcji sys.path.append
. Wykonaj ją przed uruchomieniem polecenia import
:
sys.path.append("/foo")
Teraz katalog foo
został dodany do listy ścieżek, w których szuka się modułów.
Odkrywanie modułów wbudowanych
Sprawdź pełną listę modułów wbudowanych w standardowej bibliotece Pythona tutaj.
Dwie bardzo ważne funkcje są przydatne podczas odkrywania modułów w Pythonie - funkcje dir
i help
.
Aby zaimportować moduł urllib
, który umożliwia nam tworzenie oraz czytanie danych z URLi, importujemy
moduł:
# importujemy bibliotekę
import urllib
# używamy jej
urllib.urlopen(...)
Możemy sprawdzić, które funkcje są zaimplementowane w każdym module, używając funkcji dir
:
>>> import urllib
>>> dir(urllib)
['ContentTooShortError', 'FancyURLopener', 'MAXFTPCACHE', 'URLopener', '__all__', '__builtins__',
'__doc__', '__file__', '__name__', '__package__', '__version__', '_ftperrors', '_get_proxies',
'_get_proxy_settings', '_have_ssl', '_hexdig', '_hextochr', '_hostprog', '_is_unicode', '_localhost',
'_noheaders', '_nportprog', '_passwdprog', '_portprog', '_queryprog', '_safe_map', '_safe_quoters',
'_tagprog', '_thishost', '_typeprog', '_urlopener', '_userprog', '_valueprog', 'addbase', 'addclosehook',
'addinfo', 'addinfourl', 'always_safe', 'basejoin', 'c', 'ftpcache', 'ftperrors', 'ftpwrapper', 'getproxies',
'getproxies_environment', 'getproxies_macosx_sysconf', 'i', 'localhost', 'main', 'noheaders', 'os',
'pathname2url', 'proxy_bypass', 'proxy_bypass_environment', 'proxy_bypass_macosx_sysconf', 'quote',
'quote_plus', 'reporthook', 'socket', 'splitattr', 'splithost', 'splitnport', 'splitpasswd', 'splitport',
'splitquery', 'splittag', 'splittype', 'splituser', 'splitvalue', 'ssl', 'string', 'sys', 'test', 'test1',
'thishost', 'time', 'toBytes', 'unquote', 'unquote_plus', 'unwrap', 'url2pathname', 'urlcleanup', 'urlencode',
'urlopen', 'urlretrieve']
Kiedy znajdziemy funkcję w module, którą chcemy użyć, możemy przeczytać o niej więcej używając funkcji help
, korzystając z interpretera Python:
help(urllib.urlopen)
Pisanie pakietów
Pakiety są przestrzeniami nazw zawierającymi wiele pakietów i modułów. To są po prostu katalogi, ale z pewnymi wymaganiami.
Każdy pakiet w Pythonie to katalog, który MUSI zawierać specjalny plik o nazwie __init__.py
. Ten plik, który może być pusty, wskazuje że katalog w którym się znajduje jest pakietem Pythona. Dzięki temu może być importowany w ten sam sposób, co moduł.
Jeśli tworzymy katalog o nazwie foo
, który wskazuje nazwę pakietu, możemy wtedy stworzyć moduł wewnątrz tego
pakietu o nazwie bar
. Następnie dodajemy plik __init__.py
w środku katalogu foo
.
Aby używać modułu bar
, możemy zaimportować go na dwa sposoby:
import foo.bar
lub:
from foo import bar
W pierwszym przykładzie powyżej, musimy używać prefiksu foo
za każdym razem, gdy uzyskujemy dostęp do modułu bar
. W drugim przykładzie, nie musimy, ponieważ zaimportowaliśmy moduł do przestrzeni nazw naszego modułu.
Plik __init__.py
może również decydować, które moduły pakiet eksportuje jako API, zachowując inne moduły jako wewnętrzne, przez nadpisanie zmiennej __all__
w ten sposób:
__init__.py:
__all__ = ["bar"]
Ćwiczenie
W tym ćwiczeniu wypisz alfabetycznie posortowaną listę wszystkich funkcji w module re
zawierających słowo find
.
import re
# Your code goes here
find_members = []
import re
# Your code goes here
find_members = []
for member in dir(re):
if "find" in member:
find_members.append(member)
print(sorted(find_members))
test_object('find_members')
success_msg('Great work!')
This site is generously supported by DataCamp. DataCamp offers online interactive Python Tutorials for Data Science. Join over a million other learners and get started learning Python for data science today!