Hướng dẫn package trong python
Module và package là những cấp độ quản lý code cao hơn trong Python. Module cho phép lưu trữ hàm (và code khác) trên các file riêng rẽ để sau tái sử dụng trong các file và dự án khác. Package cho phép nhóm các module lại với nhau. Sử dụng module và package giúp bạn dễ dàng quản lý code trong những chương trình lớn cũng như tái sử dụng code về sau. Show Ví dụ sử dụng module trong PythonHãy bắt đầu với
một ví dụ minh họa. Tạo hai file print('--- start of my_math ---') PI = 3.14159 E = 2.71828 message = 'My math module' def sum(start, *numbers): '''Calculate the sum of unlimited number Params: start:int/float, the start sum *numbers:int/float, the numbers to sum up Return: int/float ''' for x in numbers: start += x return start def sum_range(start, stop, step=1): ''' Calculate the sum of intergers Params: start:int, start range number stop:int, stop range number step:int, the step between value Returns: int ''' sum = 0 for i in range(start, stop, step): sum += i return sum def fact(n): '''Calculate the factorial of n Params: n:int Return: int ''' p = 1 for i in range(1, n + 1): p *= i return p print('--- start of my_math ---') import my_math print(my_math.message) sum = my_math.sum(0, 1, 2, 3, 4) sum_range = my_math.sum_range(1, 10) fact = my_math.fact(3) print('sum = ', sum) print('sum_range = ', sum_range) print('fact = ', fact) print('Pi = ', my_math.PI) print('e = ', my_math.E) Bạn cần chạy chương trình từ file main.py. Kết quả thu được như sau: File Trong file Để ý lệnh
Module trong PythonTrong Python, bất kỳ file script (file có đuôi py) đều được gọi là một module. Khi bạn tạo một file code Python mới, bạn đang tạo một module. Như vậy, ngay từ những bài học đầu tiên bạn đã xây dựng module Python. Tên module là tên file (bỏ đi phần mở rộng py). Trong ví dụ ở phần trên, Module Mỗi module đều có thể được tải và thực thi bởi Python interpreter. Như ở trên, bạn có thể chạy module my_math và main riêng rẽ vì chúng đều là các file code Python hợp lệ. Tuy nhiên, nếu bạn chạy module my_math thì sẽ không ra kết quả gì vì trong module này chúng ta chỉ định nghĩa các hàm và biến chứ không hề sử dụng chúng. Đây là điểm khác biệt giữa my_math và main: trong my_math chỉ chứa khai báo (hàm/biến), trong main chứa lời gọi. Như vậy, cách thức xây dựng và sử dụng làm cho các module khác biệt nhau. Có những module được xây dựng ra với vai trò cung cấp thư viện hàm cho module khác sử dụng. Có những module sử dụng hàm định nghĩa trong các module khác. Để sử dụng hàm/biến/kiểu dữ liệu định nghĩa trong file/module khác, Python sử dụng lệnh import. Có hai kiểu viết lệnh import khác nhau:
Sử dụng module với import …Trong ví dụ minh họa chúng ta đã sử dụng lối viết này: import my_math Cách viết này sẽ tải toàn bộ module my_math, gần giống hệt như việc copy nội dung của my_math.py đặt vào vị trí của lệnh Bạn có thể thấy điều này khi cặp lệnh print() viết ở đầu và cuối module my_math đều được thực hiện. Cách này sẽ chỉ tải module khi gặp lệnh import lần đầu tiên. Khi gặp lệnh import lần thứ hai, Python sẽ
không tải module nữa. Bạn có thể thấy rất rõ điều này khi cặp lệnh print() ở đầu và cuối module my_math chỉ được gọi một lần duy nhất trước khi bắt đầu module main mặc dù chúng ta viết lệnh Hãy để ý cách chúng ta gọi hàm và sử dụng biến (được khai báo trong module my_math): sum = my_math.sum(0, 1, 2, 3, 4) sum_range = my_math.sum_range(1, 10) fact = my_math.fact(3) print('Pi = ', my_math.PI) print('e = ', my_math.E) print(my_math.message) Tức là, thay vì viết trực tiếp tên hàm/biến, bạn phải cung cấp thêm tên module my_math. Cấu trúc chung để sử dụng một hàm/biến trong module khác là Bạn có thể sử dụng alias trong lệnh import như sau: import my_math as mm Tên print(mm.message) print(mm.sum(1, 2, 3, 4, 5)) print(mm.E) Nghĩa là bạn có thể sử dụng alias thay cho tên module. Bạn có thể đồng thời sử dụng cả tên module lẫn alias. Alias rất tiện lợi khi tên module quá dài hoặc tên module trùng lặp với một hàm/biến có sẵn của Python. Sử dụng module với from … import …Giờ hãy xóa (hoặc comment) toàn bộ code của main.py và viết lại code mới như sau: from my_math import sum_range, fact, message print(message) print('sum_range = ', sum_range(1, 100, 2)) print('5! = ', fact(5)) Ở đây chúng ta gặp cách sử dụng thứ hai của import: Khi sử dụng cấu trúc from .. import bạn có thể thấy rằng Python vẫn import toàn bộ code của module my_math (như trường hợp sử dụng Tuy nhiên, giờ đây bạn không thể sử dụng được tất cả các hàm/biến của module my_math như trước được nữa. Giờ bạn chỉ có thể sử dụng hàm Điều đặc biệt là bạn có thể sử dụng tên ngắn gọn của các đối tượng này (không cần tên module), giống hệt như khi các đối tượng này được khai báo trực tiếp trong module main: print(message) print('sum_range = ', sum_range(1, 100, 2)) print('5! = ', fact(5)) Bạn cũng có thể chỉ định alias cho từng tên gọi trong lệnh from .. import như sau: from my_math import sum_range as sr, fact as f, message as msg print(msg) print('sum_range = ', sr(1, 100, 2)) print('5! = ', f(5)) Ở đây khi import chúng ta chỉ định alias sr cho hàm sum_range(), f cho hàm fact(), msg cho biến message. Trong code sau đó chúng ta có thể sử dụng alias thay cho tên thật. Lưu ý, nếu bạn đã đặt alias thì không thể sử dụng tên thật của đối tượng được nữa. Tức là không thể đồng thời sử dụng alias và tên thật. Bạn cũng có thể sử dụng cách import như sau: from my_math import * Tuy nhiên đây là cách thức không được khuyến khích. Nó dễ dàng làm rối không gian tên của module hiện tại nếu có quá nhiều tên gọi được import. Về hiệu suất tổng thể thì cả hai cách import gần như là tương đương nhau. Sự khác biệt chỉ nằm ở cách sử dụng các đối tượng từ module. Thực thi moduleKhi xây dựng một module bạn có thể phải dự phòng hai tình huống:
Mỗi module có một thuộc tính đặc biệt tên là Khi một module được thực thi trực tiếp, Khi một module được thực thi gián tiếp, Với đặc thù trên, khi xây dựng module trong Python mà cần chạy ở cả hai kiểu (trực tiếp và gián tiếp) người ta thường sử dụng pattern sau đây:
def main(): 'Thực thi các logic của chương trình' # code cần chạy if __name__ == '__main__': main() Khi chạy gián tiếp qua import Khi một module được chạy gián tiếp qua import, Python cũng thực hiện lưu tạm bản dịch bytecode của nó trong thư
mục Nhắc lại: khi chạy một script, Python sẽ dịch nó thành bytecode trung gian. Chương trình máy ảo của Python sẽ tiếp tục dịch bytecode thành mã máy để thực thi trên từng hệ điều hành. File bytecode của Python có phần mở rộng là pyc. Khi import một module cũng xảy ra quá trình dịch bytecode như vậy. Tuy nhiên, Python sẽ lưu lại lại file pyc để lần sau không cần dịch lại. Việc lưu trữ file pyc giúp giảm thời gian tải một chương trình. Lưu ý, khi trực tiếp thực thi một module Python sẽ không lưu lại file bytecode. File bytecode không thực thi nhanh hơn. Nó chỉ giảm thời gian tải ứng dụng. Vì lý do này, khi xây dựng chương trình bằng Python bạn nên tận dụng việc xây dựng và import module, thay vì code trực tiếp trong một module chính lớn. Toàn bộ code nên đưa về các module và để module chính đơn giản nhất có thể. Vấn đề đường dẫn khi sử dụng moduleBạn có thể ý thấy khi import module bạn không hề chỉ định đường dẫn đến file script. Python thực hiện việc tìm kiếm file module tự động theo các thư mục lưu trong biến sys.path. Biến sys.path là một danh sách lưu những đường dẫn được đăng ký trong Python. Bạn có thể xem nội dung của sys.path như sau: >>> import sys >>> sys.path # đây là một list ['.', 'E:\\OneDrive\\TuHocICT\\Learn Python\\PythonApps\\HelloPython', 'F:\\Users\\thang\\AppData\\Local\\Programs\\Python\\Python38\\python38.zip', 'F:\\Users\\thang\\AppData\\Local\\Programs\\Python\\Python38\\DLLs', 'F:\\Users\\thang\\AppData\\Local\\Programs\\Python\\Python38\\lib', 'F:\\Users\\thang\\AppData\\Local\\Programs\\Python\\Python38', 'F:\\Users\\thang\\AppData\\Local\\Programs\\Python\\Python38\\lib\\site-packages'] >>> for p in sys.path: ... print(p) ... . E:\OneDrive\TuHocICT\Learn Python\PythonApps\HelloPython F:\Users\thang\AppData\Local\Programs\Python\Python38\python38.zip F:\Users\thang\AppData\Local\Programs\Python\Python38\DLLs F:\Users\thang\AppData\Local\Programs\Python\Python38\lib F:\Users\thang\AppData\Local\Programs\Python\Python38 F:\Users\thang\AppData\Local\Programs\Python\Python38\lib\site-packages Bạn có thể để ý ngay đường dẫn đầu tiên chính là thư mục làm việc (thư mục hiện hành) nơi bạn đặt file module chính. Ví dụ, nếu bạn chạy module main.py và trong main.py có lệnh import my_math thì Python trước hết sẽ tìm kiếm my_math.py trong thư mục chứa main.py. Nếu không tìm thấy file tương ứng, Python sẽ lần lượt tìm trong các thư mục còn lại. Để ý một tình huống khác. Giả sử bạn có module
mysql nằm trong file Để import module mysql bạn cần viết như sau: Nếu trong trường hợp các file module của bạn nằm ở một nơi khác (không nằm trong danh sách sys.path mặc định), bạn phải có cách chỉ định đường dẫn để Python có thể tìm thấy. Cách đơn giản nhất như sau: import sys sys.path.append('-- new path --') # thêm thư mục mới vào sys.path # giờ sẽ import module import a_module Logic ở đây rất đơn giản. Do sys.path chỉ là một list, bạn có thể tự thêm một đường dẫn mới vào sys.path. Khi đó Python sẽ tìm kiếm cả trong đường dẫn bạn thêm vào. Ví dụ: >>> import sys >>> sys.path.append('E:\OneDrive\TuHocICT\Learn Python\Modules') >>> import sample_module hello world from sample module >>> Sử dụng package trong PythonTrong Python, một số module trong cùng thư mục (và thư mục con) có thể kết hợp lại để tạo ra một package. Package giúp đơn giản hóa hơn nữa việc sử dụng nhiều module có liên quan. Hãy cùng thực hiện ví dụ sau: Tạo thư mục my_package. Trong thư mục này tạo hai file module1.py và module2.py với code như sau: print('This is the module 1') def func1(): print('Module 1 - func 1') print('This is the module 2') def func2(): print('Module 2 - func 2') Nếu dừng lại ở đây bạn sẽ có hai module riêng rẽ. Khi sử dụng bạn cần import từng module. Giờ hãy tạo file __init__.py trong thư mục my_package. Lưu ý có hai ký tự _ ở trước và sau init. Viết code như sau cho __init__.py: from my_package.module1 import * from my_package.module2 import * #hoặc cũng có thể import như thế này: #import my_package.module1 #import my_package.module2 Đây là hai lệnh import thông thường mà bạn đã học ở phần trên. Bạn có thể sử dụng kiểu import nào cũng được. Tuy nhiên cần lưu ý về cách viết tên module: Tên file __init__.py có ý nghĩa đặc thù trong Python. Nếu Python nhìn thấy thư mục nào có file với tên gọi __init__.py, nó sẽ tự động coi thư mục này là một package, chứ không còn là thư mục bình thường nữa. Bên ngoài thư mục package hãy tạo module main.py và viết code như sau: import my_package as mp mp.module1.func1() mp.module2.func2() from my_package import * module1.func1(); Bạn có thể để ý thấy ngay rằng lệnh import giờ không hoạt động với từng module nữa mà là với tên thư mục my_package. Tất cả các thư mục chứa file __init__.py sẽ trở thành một package. Tên thư mục trở thành tên package và có thể sử dụng cùng lệnh import hoặc from/import. Khi import một package bạn sẽ đồng thời import tất cả các module của nó (được chỉ định trong __init__.py). Nếu sử dụng lệnh Nếu sử dụng from Lưu ý: trong __init__.py và trong module sử dụng package nên dùng cùng một cách import. Ví dụ, cùng dùng import hoặc cùng dùng from .. import. Kết luậnTrong bài học này chúng ta đã học chi tiết cách sử dụng module trong Python:
+ Nếu bạn thấy site hữu ích, trước khi rời đi hãy giúp đỡ site bằng một hành động nhỏ để site có thể phát triển và phục vụ bạn tốt hơn. |