Python đọc vị trí

Thuộc tính

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
70 chỉ định loại phương pháp định vị được sử dụng cho một phần tử [tĩnh, tương đối, cố định, tuyệt đối hoặc dính]

Thuộc tính

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
70 chỉ định loại phương pháp định vị được sử dụng cho một phần tử

Có năm giá trị vị trí khác nhau

  • >>> import math
    >>> dir[]
    ['__annotations__', '__builtins__', ..., 'math']
    
    >>> dir[math]
    ['__doc__', ..., 'nan', 'pi', 'pow', ...]
    
    72
  • >>> import math
    >>> dir[]
    ['__annotations__', '__builtins__', ..., 'math']
    
    >>> dir[math]
    ['__doc__', ..., 'nan', 'pi', 'pow', ...]
    
    73
  • >>> import math
    >>> dir[]
    ['__annotations__', '__builtins__', ..., 'math']
    
    >>> dir[math]
    ['__doc__', ..., 'nan', 'pi', 'pow', ...]
    
    74
  • >>> import math
    >>> dir[]
    ['__annotations__', '__builtins__', ..., 'math']
    
    >>> dir[math]
    ['__doc__', ..., 'nan', 'pi', 'pow', ...]
    
    75
  • >>> import math
    >>> dir[]
    ['__annotations__', '__builtins__', ..., 'math']
    
    >>> dir[math]
    ['__doc__', ..., 'nan', 'pi', 'pow', ...]
    
    76

Các phần tử sau đó được định vị bằng cách sử dụng các thuộc tính trên cùng, dưới cùng, bên trái và bên phải. Tuy nhiên, các thuộc tính này sẽ không hoạt động trừ khi thuộc tính

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
70 được đặt trước. Chúng cũng hoạt động khác nhau tùy thuộc vào giá trị vị trí

Chức vụ. tĩnh;

Các phần tử HTML được định vị tĩnh theo mặc định

Các phần tử được định vị tĩnh không bị ảnh hưởng bởi các thuộc tính trên, dưới, trái và phải

Một phần tử với

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
78 không được định vị theo bất kỳ cách đặc biệt nào;

Đây

phần tử có vị trí. tĩnh;

Đây là CSS được sử dụng

Chức vụ. quan hệ;

Một phần tử có

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
700 được định vị so với vị trí bình thường của nó

Đặt các thuộc tính top, right, bottom và left của một phần tử được định vị tương đối sẽ khiến nó bị điều chỉnh khỏi vị trí bình thường. Nội dung khác sẽ không được điều chỉnh để phù hợp với bất kỳ khoảng trống nào do phần tử để lại

Đây

phần tử có vị trí. quan hệ;

Đây là CSS được sử dụng

Thí dụ

div. vị trí tương đối {
 . họ hàng;
  trái. 30px;
  đường viền. Chất rắn 3px #73AD21;
}

Tự mình thử »

Chức vụ. đã sửa;

Một phần tử có

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
701 được định vị so với khung nhìn, có nghĩa là nó luôn ở cùng một vị trí ngay cả khi trang được cuộn. Các thuộc tính top, right, bottom, left dùng để định vị phần tử

Phần tử cố định không để lại khoảng trống trên trang mà nó thường được đặt

Lưu ý phần tử cố định ở góc dưới bên phải của trang. Đây là CSS được sử dụng

Thí dụ

div. vị trí {
  đã cố định. đã sửa;
  dưới cùng. 0;
  đúng. 0;
  chiều rộng. 300px;
  đường viền. Chất rắn 3px #73AD21;
}

Tự mình thử »

Đây

phần tử có

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
701

Chức vụ. tuyệt đối;

Một phần tử có

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
703 được định vị tương đối so với tổ tiên được định vị gần nhất [thay vì được định vị tương ứng với chế độ xem, như cố định]

Tuy nhiên;

Ghi chú. Các phần tử được định vị tuyệt đối bị xóa khỏi luồng thông thường và có thể chồng lấp các phần tử

Đây là một ví dụ đơn giản

Đây

phần tử có vị trí. quan hệ;

Đây

phần tử có vị trí. tuyệt đối;

Đây là CSS được sử dụng

Thí dụ

div. vị trí tương đối {
  . tương đối;
  chiều rộng. 400px;
  chiều cao. 200px;
  đường viền. Chất rắn 3px #73AD21;
}

div. {
  vị trí tuyệt đối. tuyệt đối;
  trên cùng. 80px;
  phải. 0;
  chiều rộng. 200px;
  chiều cao. 100px;
  đường viền. Chất rắn 3px #73AD21;
}

Tự mình thử »

Chức vụ. nếp;

Một phần tử có

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
704 được định vị dựa trên vị trí cuộn của người dùng

Phần tử cố định chuyển đổi giữa

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
73 và
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
74, tùy thuộc vào vị trí cuộn. Nó được định vị tương đối cho đến khi một vị trí bù nhất định được đáp ứng trong chế độ xem - sau đó nó "dính" vào vị trí [như vị trí. đã sửa]

Ghi chú. Internet Explorer không hỗ trợ định vị cố định. Safari yêu cầu tiền tố -webkit- [xem ví dụ bên dưới]. Bạn cũng phải chỉ định ít nhất một trong số

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
707,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
708,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
709 hoặc
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
700 để định vị cố định hoạt động

Trong ví dụ này, phần tử cố định dính vào đầu trang [

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
701], khi bạn đến vị trí cuộn của nó

Trong Python, bạn sử dụng từ khóa

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
44 để tạo mã trong một mô-đun có sẵn trong một mô-đun khác. Nhập trong Python rất quan trọng để cấu trúc mã của bạn một cách hiệu quả. Sử dụng nhập đúng cách sẽ giúp bạn làm việc hiệu quả hơn, cho phép bạn sử dụng lại mã trong khi vẫn duy trì dự án của mình

Hướng dẫn này sẽ cung cấp một cái nhìn tổng quan về câu lệnh

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
44 của Python và cách thức hoạt động của nó. Hệ thống nhập rất mạnh và bạn sẽ học cách khai thác sức mạnh này. Mặc dù bạn sẽ đề cập đến nhiều khái niệm đằng sau hệ thống nhập của Python, hướng dẫn này chủ yếu dựa trên ví dụ. Bạn sẽ học được từ một số ví dụ mã trong suốt

Trong hướng dẫn này, bạn sẽ học cách

  • Sử dụng các mô-đun, gói và gói không gian tên
  • Xử lý các tệp tài nguyên và dữ liệu bên trong các gói của bạn
  • Nhập mô-đun động khi chạy
  • Tùy chỉnh hệ thống nhập của Python

Xuyên suốt hướng dẫn, bạn sẽ thấy các ví dụ về cách chơi với bộ máy nhập Python để hoạt động hiệu quả nhất. Mặc dù tất cả mã được hiển thị trong hướng dẫn, nhưng bạn cũng có thể tải xuống bằng cách nhấp vào hộp bên dưới

Lấy mã nguồn. Nhấp vào đây để lấy mã nguồn mà bạn sẽ sử dụng để tìm hiểu về hệ thống nhập Python trong hướng dẫn này

Python cơ bản
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
44

Mã Python được tổ chức thành cả mô-đun và gói. Phần này sẽ giải thích chúng khác nhau như thế nào và bạn có thể làm việc với chúng như thế nào

Ở phần sau của hướng dẫn, bạn sẽ thấy một số cách sử dụng nâng cao và ít được biết đến của hệ thống nhập của Python. Tuy nhiên, hãy bắt đầu với những điều cơ bản. nhập mô-đun và gói

Loại bỏ các quảng cáo

mô-đun

con trăn. thuật ngữ org định nghĩa mô-đun như sau

Một đối tượng phục vụ như một đơn vị tổ chức của mã Python. Các mô-đun có một không gian tên chứa các đối tượng Python tùy ý. Các mô-đun được tải vào Python bằng quá trình nhập. [Nguồn]

Trong thực tế, một mô-đun thường tương ứng với một tệp

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
47 chứa mã Python

Sức mạnh thực sự của các mô-đun là chúng có thể được nhập và sử dụng lại trong mã khác. Xem xét ví dụ sau

>>>

>>> import math
>>> math.pi
3.141592653589793

Trong dòng đầu tiên,

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
48, bạn nhập mã trong mô-đun
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 và cung cấp mã đó để sử dụng. Ở dòng thứ hai, bạn truy cập biến
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
50 trong mô-đun
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49.
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 là một phần của thư viện chuẩn của Python, có nghĩa là nó luôn có sẵn để nhập khi bạn chạy Python

Lưu ý rằng bạn viết

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
53 và không chỉ đơn giản là
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
50. Ngoài vai trò là một mô-đun,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 hoạt động như một không gian tên giữ tất cả các thuộc tính của mô-đun lại với nhau. Không gian tên rất hữu ích để giữ cho mã của bạn dễ đọc và có tổ chức. Theo lời của Tim Peters

Không gian tên là một ý tưởng tuyệt vời—hãy làm nhiều hơn nữa. [Nguồn]

Bạn có thể liệt kê nội dung của một không gian tên với

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
56

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]

Sử dụng

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
56 mà không có bất kỳ đối số nào sẽ hiển thị những gì trong không gian tên chung. Để xem nội dung của không gian tên
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49, bạn sử dụng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
59

Bạn đã thấy cách sử dụng đơn giản nhất của

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
44. Tuy nhiên, có nhiều cách khác để sử dụng nó cho phép bạn nhập các phần cụ thể của mô-đun và đổi tên mô-đun khi bạn nhập mô-đun đó

Đoạn mã sau chỉ nhập biến

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
50 từ mô-đun
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
1

Lưu ý rằng nơi này đặt

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
50 trong không gian tên chung chứ không phải trong không gian tên
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49

Bạn cũng có thể đổi tên các mô-đun và thuộc tính khi chúng được nhập

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
4

Để biết thêm chi tiết về cú pháp nhập mô-đun, hãy xem Mô-đun và Gói Python – Giới thiệu

gói

Bạn có thể sử dụng một gói để tổ chức thêm các mô-đun của mình. con trăn. thuật ngữ org định nghĩa gói như sau

Một mô-đun Python có thể chứa các mô-đun con hoặc đệ quy, các gói con. Về mặt kỹ thuật, một gói là một mô-đun Python có thuộc tính

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
65. [Nguồn]

Lưu ý rằng một gói vẫn là một mô-đun. Là người dùng, bạn thường không cần phải lo lắng về việc bạn đang nhập mô-đun hay gói

Trong thực tế, một gói thường tương ứng với một thư mục tệp chứa các tệp Python và các thư mục khác. Để tự tạo một gói Python, bạn tạo một thư mục và một tệp có tên

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
66 bên trong nó. Tệp
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
66 chứa nội dung của gói khi được coi là mô-đun. Nó có thể để trống

Ghi chú. Các thư mục không có tệp

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
66 vẫn được Python coi là gói. Tuy nhiên, đây sẽ không phải là các gói thông thường, mà là một thứ gọi là gói không gian tên. Bạn sẽ tìm hiểu thêm về chúng sau

Nói chung, các mô-đun con và gói con không được nhập khi bạn nhập một gói. Tuy nhiên, bạn có thể sử dụng

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
66 để bao gồm bất kỳ hoặc tất cả các mô hình con và gói con nếu bạn muốn. Để hiển thị một vài ví dụ về hành vi này, bạn sẽ tạo một gói để nói
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
70 bằng một vài ngôn ngữ khác nhau. Gói này sẽ bao gồm các thư mục và tệp sau

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
1

Mỗi tệp quốc gia in ra một lời chào, trong khi tệp

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
66 nhập có chọn lọc một số gói con và mô hình con. Nội dung chính xác của các tập tin như sau

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
3

Lưu ý rằng

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
72 chỉ nhập khẩu
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
73 chứ không phải
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
74. Tương tự,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
75 không nhập bất cứ thứ gì, trong khi
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
76 nhập
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
77 và
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
78 nhưng không nhập
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
79. Mỗi mô-đun quốc gia sẽ in lời chào khi được nhập

Hãy chơi với gói

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
80 tại dấu nhắc tương tác để hiểu rõ hơn về cách hoạt động của các gói con và mô-đun con

>>>

>>> import math
>>> math.pi
3.141592653589793
3

Khi

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
74 được nhập, các mô-đun
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
82 và
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
83 cũng được nhập. Bạn có thể thấy điều này vì các mô-đun quốc gia in lời chào khi chúng được nhập

>>>

>>> import math
>>> math.pi
3.141592653589793
7

Tệp

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
75 trống. Điều này có nghĩa là việc nhập gói
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
85 sẽ tạo không gian tên nhưng không có tác dụng nào khác

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
0

Hãy nhớ rằng, nhập một mô-đun vừa tải nội dung vừa tạo một không gian tên chứa nội dung. Một vài ví dụ cuối cùng cho thấy rằng cùng một mô-đun có thể là một phần của các không gian tên khác nhau

Chi tiết kỹ thuật. Không gian tên mô-đun được triển khai dưới dạng từ điển Python và có sẵn tại thuộc tính

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
86

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
2

Bạn hiếm khi cần tương tác trực tiếp với

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
86

Tương tự, không gian tên toàn cục của Python cũng là một từ điển. Bạn có thể truy cập nó thông qua

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
88

Việc nhập các gói con và mô-đun con trong tệp

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
66 là khá phổ biến để cung cấp chúng dễ dàng hơn cho người dùng của bạn. Bạn có thể xem một ví dụ về điều này trong gói
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
90 phổ biến

Loại bỏ các quảng cáo

Nhập khẩu tuyệt đối và tương đối

Nhớ lại mã nguồn của

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
72 trong ví dụ trước

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
0

Bạn đã từng thấy các câu lệnh của

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
92 chẳng hạn như
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
93, nhưng dấu chấm [
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
94] trong
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
95 có nghĩa là gì?

Dấu chấm đề cập đến gói hiện tại và câu lệnh là một ví dụ về nhập tương đối. Bạn có thể đọc nó là “Từ gói hiện tại, nhập gói phụ

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
73. ”

Có một câu lệnh nhập tuyệt đối tương đương trong đó bạn đặt tên rõ ràng cho gói hiện tại

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
1

Trên thực tế, tất cả các lần nhập trong

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
80 có thể đã được thực hiện rõ ràng với các lần nhập tuyệt đối tương tự

Nhập tương đối phải ở dạng

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
92 và vị trí bạn đang nhập phải bắt đầu bằng dấu chấm

Hướng dẫn kiểu PEP 8 khuyến nghị sử dụng nhập khẩu tuyệt đối nói chung. Tuy nhiên, nhập khẩu tương đối là một giải pháp thay thế để tổ chức phân cấp gói. Để biết thêm thông tin, hãy xem Nhập tuyệt đối và tương đối trong Python

Đường dẫn nhập của Python

Làm cách nào để Python tìm thấy các mô-đun và gói mà nó nhập? . Hiện tại, chỉ cần biết rằng Python tìm kiếm các mô-đun và gói trong đường dẫn nhập của nó. Đây là danh sách các vị trí được tìm kiếm các mô-đun để nhập

Ghi chú. Khi bạn nhập

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
99, Python sẽ tìm kiếm
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
100 ở một số vị trí khác nhau trước khi tìm kiếm đường dẫn nhập

Cụ thể, nó sẽ tìm kiếm trong bộ đệm mô-đun để xem liệu

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
100 đã được nhập chưa và nó sẽ tìm kiếm trong số các mô-đun tích hợp

Bạn sẽ tìm hiểu thêm về bộ máy nhập Python đầy đủ trong phần sau

Bạn có thể kiểm tra đường dẫn nhập của Python bằng cách in

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
102. Nói chung, danh sách này sẽ chứa ba loại địa điểm khác nhau

  1. Thư mục của tập lệnh hiện tại [hoặc thư mục hiện tại nếu không có tập lệnh nào, chẳng hạn như khi Python đang chạy tương tác]
  2. Nội dung của biến môi trường
    >>> import math
    >>> dir[]
    ['__annotations__', '__builtins__', ..., 'math']
    
    >>> dir[math]
    ['__doc__', ..., 'nan', 'pi', 'pow', ...]
    
    103
  3. Các thư mục phụ thuộc vào cài đặt khác

Thông thường, Python sẽ bắt đầu ở đầu danh sách các vị trí và tìm kiếm một mô-đun nhất định ở mỗi vị trí cho đến khi khớp đầu tiên. Vì thư mục tập lệnh hoặc thư mục hiện tại luôn ở vị trí đầu tiên trong danh sách này, nên bạn có thể đảm bảo rằng các tập lệnh của mình tìm thấy các mô-đun và gói tự tạo bằng cách tổ chức các thư mục của bạn và cẩn thận về việc bạn chạy Python từ thư mục nào

Tuy nhiên, bạn cũng nên cẩn thận rằng bạn không tạo các mô-đun che khuất hoặc ẩn các mô-đun quan trọng khác. Ví dụ, giả sử bạn xác định mô-đun

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 sau

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
2

Sử dụng mô-đun này hoạt động như mong đợi

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
3

Nhưng mô-đun này cũng phủ bóng mô-đun

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 có trong thư viện chuẩn. Thật không may, điều đó có nghĩa là ví dụ tra cứu giá trị của π trước đây của chúng tôi không còn hoạt động nữa

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
4

Vấn đề là Python hiện tìm kiếm mô-đun

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 mới của bạn cho
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
50 thay vì tìm kiếm mô-đun
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 trong thư viện chuẩn

Để tránh các loại sự cố này, bạn nên cẩn thận với tên của các mô-đun và gói của mình. Cụ thể, tên gói và mô-đun cấp cao nhất của bạn phải là duy nhất. Nếu

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 được định nghĩa là một mô-đun con trong một gói, thì nó sẽ không che khuất mô-đun tích hợp

Loại bỏ các quảng cáo

Thí dụ. Cấu trúc nhập khẩu của bạn

Mặc dù có thể tổ chức quá trình nhập của bạn bằng cách sử dụng thư mục hiện tại cũng như bằng cách thao tác với

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
103 và thậm chí là
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
102, quá trình này thường không theo quy tắc và dễ xảy ra lỗi. Để xem một ví dụ điển hình, hãy xem xét ứng dụng sau

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
5

Ứng dụng sẽ tạo lại cấu trúc tệp đã cho bằng cách tạo thư mục và tệp trống. Tệp

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
112 chứa tập lệnh chính và
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
113 là mô-đun thư viện có một số chức năng để xử lý tệp. Sau đây là một ví dụ về đầu ra từ ứng dụng, trong trường hợp này bằng cách chạy nó trong thư mục
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
114

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
6

Hai tệp mã nguồn cũng như tệp

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
115 được tạo tự động được tạo lại bên trong một thư mục mới có tên là
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
116

Bây giờ hãy xem mã nguồn. Chức năng chính của ứng dụng được xác định trong

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
112

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
7

Trong các dòng 12 đến 16, bạn đọc đường dẫn gốc từ dòng lệnh. Trong ví dụ trên bạn sử dụng dấu chấm, có nghĩa là thư mục hiện tại. Đường dẫn này sẽ được sử dụng làm

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
118 của hệ thống phân cấp tệp mà bạn sẽ tạo lại

Công việc thực tế xảy ra ở dòng 19 đến 23. Trước tiên, bạn tạo một đường dẫn duy nhất,

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
119, đây sẽ là gốc của hệ thống phân cấp tệp mới của bạn. Sau đó, bạn lặp qua tất cả các đường dẫn bên dưới bản gốc
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
118 và tạo lại chúng dưới dạng các tệp trống bên trong hệ thống phân cấp tệp mới

Để thao tác với các đường dẫn như thế này,

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
121 trong thư viện tiêu chuẩn khá hữu ích. Để biết thêm chi tiết về cách nó được sử dụng, hãy xem Mô-đun
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
121 của Python 3. Thuần hóa hệ thống tập tin

Trên dòng 26, bạn gọi

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
123. Bạn sẽ tìm hiểu thêm về bài kiểm tra
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
124 ở dòng 25 sau. Bây giờ, bạn nên biết rằng biến đặc biệt
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
125 có giá trị
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
126 bên trong các tập lệnh, nhưng nó lấy tên của mô-đun bên trong các mô-đun đã nhập. Để biết thêm thông tin về
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
125, hãy xem Xác định hàm chính trong Python và Điều gì sẽ xảy ra nếu tên == “chính” Làm trong Python?

Lưu ý rằng bạn nhập

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
128 trên dòng 8. Mô-đun thư viện này chứa hai chức năng tiện ích

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
8

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
129 sử dụng bộ đếm để tìm đường dẫn chưa tồn tại. Trong ứng dụng, bạn sử dụng nó để tìm một thư mục con duy nhất để sử dụng làm
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
119 của hệ thống phân cấp tệp được tạo lại. Tiếp theo,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
131 đảm bảo rằng tất cả các thư mục cần thiết đã được tạo trước khi tạo một tệp trống bằng cách sử dụng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
132

Hãy xem lại việc nhập

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
128

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
9

Nó trông khá ngây thơ. Tuy nhiên, khi dự án phát triển, dòng này sẽ khiến bạn đau đầu. Mặc dù bạn nhập

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
128 từ dự án
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
114, việc nhập là tuyệt đối. nó không bắt đầu bằng dấu chấm. Điều này có nghĩa là phải tìm thấy
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
128 trong đường dẫn nhập để quá trình nhập hoạt động

May mắn thay, thư mục chứa tập lệnh hiện tại luôn nằm trong đường dẫn nhập của Python, vì vậy hiện tại nó hoạt động tốt. Tuy nhiên, nếu dự án của bạn đạt được một số lực kéo, thì nó có thể được sử dụng theo những cách khác

Ví dụ: ai đó có thể muốn nhập tập lệnh vào Jupyter Notebook và chạy tập lệnh từ đó. Hoặc họ có thể muốn sử dụng lại thư viện

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
128 trong một dự án khác. Họ thậm chí có thể tạo một tệp thực thi bằng PyInstaller để phân phối dễ dàng hơn. Thật không may, bất kỳ tình huống nào trong số này đều có thể tạo ra sự cố khi nhập
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
128

Để xem ví dụ, bạn có thể làm theo hướng dẫn PyInstaller và tạo một điểm vào cho ứng dụng của mình. Thêm một thư mục bổ sung bên ngoài thư mục ứng dụng của bạn

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
10

Trong thư mục bên ngoài, tạo tập lệnh điểm vào,

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
139

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
11

Tập lệnh này sẽ nhập

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
123 từ tập lệnh gốc của bạn và chạy nó. Lưu ý rằng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
123 không chạy khi
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
114 được nhập vì thử nghiệm
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
124 trên dòng 25 trong
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
112. Điều đó có nghĩa là bạn cần chạy
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
123 một cách rõ ràng

Về lý thuyết, điều này sẽ hoạt động tương tự như chạy ứng dụng trực tiếp

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
12

Tại sao nó không hoạt động?

Vấn đề là khi khởi động ứng dụng bằng

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
139, bạn đã thay đổi vị trí của tập lệnh hiện tại, do đó thay đổi đường dẫn nhập.
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
128 không còn trên đường dẫn nhập, vì vậy không thể nhập hoàn toàn

Một giải pháp khả thi là thay đổi đường dẫn nhập của Python

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
13

Điều này hoạt động vì đường dẫn nhập bao gồm thư mục chứa

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
112 và
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
113. Vấn đề với phương pháp này là đường dẫn nhập của bạn có thể rất lộn xộn và khó hiểu

Trên thực tế, bạn đang tạo lại một tính năng của các phiên bản Python đầu tiên được gọi là nhập tương đối ngầm định. Chúng đã bị xóa khỏi ngôn ngữ bởi PEP 328 với lý do sau

Trong Python 2. 4 trở về trước, nếu bạn đang đọc một mô-đun nằm bên trong một gói, thì không rõ liệu

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
151 đề cập đến một mô-đun cấp cao nhất hay một mô-đun khác bên trong gói. Khi thư viện của Python mở rộng, ngày càng có nhiều mô-đun bên trong gói hiện có đột nhiên che khuất các mô-đun thư viện tiêu chuẩn một cách tình cờ. Đây là một vấn đề đặc biệt khó khăn bên trong các gói vì không có cách nào để chỉ định mô-đun nào có nghĩa là. [Nguồn]

Một giải pháp khác là sử dụng nhập tương đối thay thế. Thay đổi quá trình nhập trong

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
112 như sau

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
14

Giờ đây, bạn có thể bắt đầu ứng dụng của mình thông qua tập lệnh nhập cảnh

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
15

Thật không may, bạn không còn có thể gọi ứng dụng trực tiếp

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
16

Vấn đề là các lần nhập tương đối được giải quyết khác nhau trong các tập lệnh so với các mô-đun đã nhập. Tất nhiên, bạn có thể quay lại và khôi phục quá trình nhập tuyệt đối trước khi chạy tập lệnh trực tiếp hoặc thậm chí bạn có thể thực hiện một số động tác nhào lộn

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
153 để nhập tệp hoàn toàn hoặc tương đối tùy thuộc vào những gì hoạt động

Thậm chí còn có một bản hack bị xử phạt chính thức để làm cho hoạt động nhập tương đối trong các tập lệnh. Thật không may, điều này cũng buộc bạn phải thay đổi

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
102 trong hầu hết các trường hợp. Trích lời Raymond Hettinger

Phải có cách tốt hơn. [Nguồn]

Thật vậy, một giải pháp tốt hơn—và ổn định hơn—là sử dụng cùng với hệ thống nhập và đóng gói của Python và cài đặt dự án của bạn dưới dạng gói cục bộ bằng cách sử dụng

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
155

Loại bỏ các quảng cáo

Tạo và cài đặt gói cục bộ

Khi bạn cài đặt một gói từ PyPI, gói đó có sẵn cho tất cả các tập lệnh trong môi trường của bạn. Tuy nhiên, bạn cũng có thể cài đặt các gói từ máy tính cục bộ của mình và chúng cũng sẽ được cung cấp theo cách tương tự

Tạo một gói cục bộ không liên quan đến nhiều chi phí. Đầu tiên, tạo các tệp

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
156 và
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
157 tối thiểu trong thư mục
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
114 bên ngoài

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
17

Về lý thuyết,

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
159 và
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
160 có thể là bất cứ thứ gì bạn thích. Tuy nhiên, chúng sẽ được sử dụng bởi
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
155 khi đề cập đến gói của bạn, vì vậy bạn nên chọn các giá trị dễ nhận biết và không xung đột với các gói khác mà bạn sử dụng

Một mẹo là cung cấp cho tất cả các gói cục bộ như vậy một tiền tố chung như

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
162 hoặc tên người dùng của bạn.
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
163 nên liệt kê thư mục hoặc các thư mục chứa mã nguồn của bạn. Sau đó, bạn có thể cài đặt gói cục bộ bằng cách sử dụng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
155

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
18

Lệnh này sẽ cài đặt gói vào hệ thống của bạn. Sau đó,

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
114 sẽ được tìm thấy trên đường dẫn nhập của Python, nghĩa là bạn có thể sử dụng nó ở bất cứ đâu mà không phải lo lắng về thư mục tập lệnh, quá trình nhập tương đối hoặc các biến chứng khác. Tùy chọn
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
166 có nghĩa là có thể chỉnh sửa, tùy chọn này rất quan trọng vì tùy chọn này cho phép bạn thay đổi mã nguồn của gói mà không cần cài đặt lại

Ghi chú. Loại tệp thiết lập này hoạt động rất tốt khi bạn tự làm việc với các dự án. Tuy nhiên, nếu bạn định chia sẻ mã với người khác thì bạn nên thêm một số thông tin khác vào tệp thiết lập của mình

Để biết thêm chi tiết về các tệp thiết lập, hãy xem Cách xuất bản Gói Python mã nguồn mở lên PyPI

Giờ đây,

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
114 đã được cài đặt trên hệ thống của bạn, bạn có thể sử dụng câu lệnh nhập sau

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
19

Điều này sẽ hoạt động bất kể bạn kết thúc cuộc gọi ứng dụng của mình như thế nào

Mẹo. Trong mã của riêng bạn, bạn nên tách biệt các tập lệnh và thư viện một cách có ý thức. Đây là một quy tắc tốt

  • Một kịch bản có nghĩa là để được chạy
  • Một thư viện có nghĩa là được nhập khẩu

Bạn có thể có mã mà bạn muốn tự chạy và nhập từ các tập lệnh khác. Trong trường hợp đó, thường đáng để cấu trúc lại mã của bạn để bạn chia phần chung thành một mô-đun thư viện

Mặc dù nên tách biệt các tập lệnh và thư viện, nhưng tất cả các tệp Python đều có thể được thực thi và nhập. Trong phần sau, bạn sẽ tìm hiểu thêm về cách tạo các mô-đun xử lý tốt cả hai

Gói không gian tên

Các mô-đun và gói Python có liên quan rất chặt chẽ với các tệp và thư mục. Điều này khiến Python khác biệt với nhiều ngôn ngữ lập trình khác, trong đó các gói chỉ hoạt động như các không gian tên mà không thực thi cách tổ chức mã nguồn. Xem các cuộc thảo luận trong PEP 402 để biết ví dụ

Các gói không gian tên đã có sẵn trong Python kể từ phiên bản 3. 3. Chúng ít phụ thuộc vào hệ thống phân cấp tệp cơ bản. Đặc biệt, các gói không gian tên có thể được chia thành nhiều thư mục. Gói không gian tên được tạo tự động nếu bạn có một thư mục chứa tệp

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
47 nhưng không có tệp
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
66. Xem PEP 420 để được giải thích chi tiết

Ghi chú. Nói chính xác, các gói không gian tên ẩn đã được giới thiệu trong Python 3. 3. Trong các phiên bản trước của Python, bạn có thể tạo thủ công các gói không gian tên theo một số cách không tương thích khác nhau. PEP 420 thống nhất và đơn giản hóa các phương pháp trước đó

Để hiểu rõ hơn về lý do tại sao các gói không gian tên có thể hữu ích, hãy thử triển khai một. Như một ví dụ thúc đẩy, bạn sẽ có một cách khác để giải quyết vấn đề trong Mẫu phương thức xuất xưởng và triển khai của nó trong Python. được cung cấp một đối tượng

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
170, bạn muốn chuyển đổi nó thành một trong số các biểu diễn chuỗi. Nói cách khác, bạn muốn tuần tự hóa các đối tượng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
170

Để cụ thể hơn, bạn muốn triển khai mã hoạt động giống như thế này

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
40

Giả sử rằng bạn may mắn và bắt gặp một triển khai của bên thứ ba cho một số định dạng mà bạn cần sắp xếp theo thứ tự và nó được tổ chức dưới dạng gói không gian tên

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
41

Tệp

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
172 chứa mã có thể tuần tự hóa một đối tượng thành định dạng JSON

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
42

Giao diện bộ nối tiếp này có một chút hạn chế, nhưng nó sẽ đủ để chứng minh cách các gói không gian tên hoạt động

Tệp

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
173 chứa một
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
174 tương tự có thể chuyển đổi một đối tượng thành XML

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
43

Lưu ý rằng cả hai lớp này đều triển khai cùng một giao diện với các phương thức

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
175,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
176 và
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
177

Sau đó, bạn tạo một lớp

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
170 có thể sử dụng các bộ nối tiếp này

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
44

Một

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
170 được xác định bởi ID, tiêu đề và nghệ sĩ của nó. Lưu ý rằng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
180 không cần biết nó chuyển đổi sang định dạng nào vì nó sử dụng giao diện chung được xác định trước đó

Giả sử rằng bạn đã cài đặt gói

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
181 của bên thứ ba, bạn có thể sử dụng nó như sau

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
45

Bằng cách cung cấp các đối tượng nối tiếp khác nhau cho

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
180, bạn sẽ nhận được các bản trình bày khác nhau cho bài hát của mình

Ghi chú. Bạn có thể nhận được một

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
183 hoặc một
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
184 khi tự chạy mã. Điều này là do
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
181 không có trong đường dẫn nhập Python của bạn. Bạn sẽ sớm biết cách giải quyết vấn đề đó

Càng xa càng tốt. Tuy nhiên, bây giờ bạn nhận ra rằng bạn cũng cần chuyển đổi các bài hát của mình sang biểu diễn YAML, không được hỗ trợ trong thư viện của bên thứ ba. Nhập sự kỳ diệu của các gói không gian tên. bạn có thể thêm

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
186 của riêng mình vào gói
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
181 mà không cần chạm vào thư viện của bên thứ ba

Đầu tiên, tạo một thư mục trên hệ thống tệp cục bộ của bạn có tên là

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
181. Điều quan trọng là tên của thư mục phải khớp với tên của gói không gian tên mà bạn đang tùy chỉnh

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
46

Trong tệp

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
189, bạn xác định
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
186 của riêng mình. Bạn căn cứ vào gói
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
191, gói này phải được cài đặt từ PyPI

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
47

Vì YAML và JSON có các định dạng khá giống nhau nên bạn có thể sử dụng lại hầu hết việc triển khai của

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
192

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
48

Lưu ý rằng

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
186 dựa trên
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
192, được nhập từ chính
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
181. Vì cả
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
196 và
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
197 đều là một phần của cùng một gói không gian tên, bạn thậm chí có thể sử dụng nhập tương đối.
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
198

Tiếp tục ví dụ trên, bây giờ bạn cũng có thể chuyển đổi bài hát sang YAML

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49

Cũng giống như các gói và mô-đun thông thường, các gói không gian tên phải được tìm thấy trên đường dẫn nhập Python. Nếu bạn đang làm theo các ví dụ trước, thì bạn có thể đã gặp sự cố với việc Python không tìm thấy

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
181. Trong mã thực tế, bạn sẽ sử dụng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
155 để cài đặt thư viện của bên thứ ba, do đó, nó sẽ tự động nằm trong đường dẫn của bạn

Ghi chú. Trong ví dụ ban đầu, việc lựa chọn bộ nối tiếp được thực hiện linh hoạt hơn. Bạn sẽ thấy cách sử dụng các gói không gian tên theo mẫu phương thức xuất xưởng thích hợp sau này

Bạn cũng nên đảm bảo rằng thư viện cục bộ của mình có sẵn như một gói thông thường. Như đã giải thích ở trên, bạn có thể thực hiện việc này bằng cách chạy Python từ thư mục thích hợp hoặc bằng cách sử dụng

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
155 để cài đặt thư viện cục bộ.

Trong ví dụ này, bạn đang kiểm tra cách tích hợp gói bên thứ ba giả mạo với gói cục bộ của mình. Nếu

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
402 là một gói thực, thì bạn sẽ tải xuống từ PyPI bằng cách sử dụng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
155. Vì điều này là không thể, bạn có thể mô phỏng nó bằng cách cài đặt
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
402 cục bộ giống như bạn đã làm trong ví dụ
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
114 trước đó

Ngoài ra, bạn có thể gây rối với đường dẫn nhập của mình. Đặt các thư mục

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
402 và
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
407 trong cùng một thư mục, sau đó tùy chỉnh đường dẫn Python của bạn như sau

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
10

Giờ đây, bạn có thể sử dụng tất cả các bộ nối tiếp mà không phải lo lắng về việc chúng được xác định trong gói của bên thứ ba hay cục bộ

Loại bỏ các quảng cáo

Hướng dẫn phong cách nhập khẩu

PEP 8, hướng dẫn kiểu Python, có một số đề xuất về nhập. Như mọi khi với Python, giữ cho mã của bạn vừa có thể đọc được vừa có thể bảo trì là một điều quan trọng cần cân nhắc. Dưới đây là một số quy tắc chung về cách tạo kiểu cho hàng nhập của bạn

  • Giữ nhập ở đầu tệp
  • Viết nhập khẩu trên các dòng riêng biệt
  • Tổ chức nhập khẩu thành các nhóm. nhập thư viện tiêu chuẩn đầu tiên, sau đó nhập của bên thứ ba và cuối cùng là nhập thư viện hoặc ứng dụng cục bộ
  • Đặt hàng nhập khẩu theo thứ tự bảng chữ cái trong mỗi nhóm
  • Thích nhập khẩu tuyệt đối hơn nhập khẩu tương đối
  • Tránh nhập ký tự đại diện như
    >>> import math
    >>> dir[]
    ['__annotations__', '__builtins__', ..., 'math']
    
    >>> dir[math]
    ['__doc__', ..., 'nan', 'pi', 'pow', ...]
    
    408

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
409 và
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
410 là những công cụ tuyệt vời để thực thi một phong cách nhất quán đối với hàng nhập của bạn

Đây là một ví dụ về phần nhập bên trong gói trình đọc nguồn cấp Python thực

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
11

Lưu ý cách nhóm này làm cho các phụ thuộc của mô-đun này rõ ràng.

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
411 và
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
412 cần được cài đặt trên hệ thống. Nói chung, bạn có thể cho rằng thư viện tiêu chuẩn có sẵn. Việc tách nhập khẩu từ bên trong gói của bạn cung cấp cho bạn một số tổng quan về các phụ thuộc nội bộ của mã của bạn

Có những trường hợp nên bẻ cong các quy tắc này một chút. Bạn đã thấy rằng nhập tương đối có thể là một giải pháp thay thế cho việc tổ chức phân cấp gói. Sau này, bạn sẽ thấy trong một số trường hợp, bạn có thể di chuyển quá trình nhập vào định nghĩa hàm để phá vỡ các chu kỳ nhập như thế nào

Nhập tài nguyên

Đôi khi, bạn sẽ có mã phụ thuộc vào tệp dữ liệu hoặc các tài nguyên khác. Trong các tập lệnh nhỏ, đây không phải là vấn đề—bạn có thể chỉ định đường dẫn đến tệp dữ liệu của mình và tiếp tục

Tuy nhiên, nếu tệp tài nguyên quan trọng đối với gói của bạn và bạn muốn phân phối gói của mình cho những người dùng khác, thì một số thách thức sẽ phát sinh

  1. Bạn sẽ không có quyền kiểm soát đường dẫn đến tài nguyên vì điều đó sẽ phụ thuộc vào thiết lập của người dùng cũng như cách gói được phân phối và cài đặt. Bạn có thể cố gắng tìm ra đường dẫn tài nguyên dựa trên các thuộc tính

    >>> import math
    >>> dir[]
    ['__annotations__', '__builtins__', ..., 'math']
    
    >>> dir[math]
    ['__doc__', ..., 'nan', 'pi', 'pow', ...]
    
    413 hoặc
    >>> import math
    >>> dir[]
    ['__annotations__', '__builtins__', ..., 'math']
    
    >>> dir[math]
    ['__doc__', ..., 'nan', 'pi', 'pow', ...]
    
    65 của gói, nhưng điều này có thể không phải lúc nào cũng hoạt động như mong đợi

  2. Gói của bạn có thể nằm trong tệp ZIP hoặc tệp

    >>> import math
    >>> dir[]
    ['__annotations__', '__builtins__', ..., 'math']
    
    >>> dir[math]
    ['__doc__', ..., 'nan', 'pi', 'pow', ...]
    
    415 cũ, trong trường hợp đó, tài nguyên thậm chí sẽ không phải là tệp vật lý trên hệ thống của người dùng

Đã có một số nỗ lực giải quyết những thách thức này, bao gồm cả

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
416. Tuy nhiên, với việc đưa
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417 vào thư viện chuẩn trong Python 3. 7, hiện có một cách tiêu chuẩn để xử lý các tệp tài nguyên

Giới thiệu
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417 cấp quyền truy cập vào tài nguyên trong các gói. Trong ngữ cảnh này, tài nguyên là bất kỳ tệp nào nằm trong gói có thể nhập. Tệp có thể tương ứng hoặc không tương ứng với tệp vật lý trên hệ thống tệp

Điều này có một vài lợi thế. Bằng cách sử dụng lại hệ thống nhập, bạn sẽ có cách xử lý nhất quán hơn với các tệp bên trong các gói của mình. Nó cũng cho phép bạn truy cập dễ dàng hơn vào các tệp tài nguyên trong các gói khác. Các tài liệu tổng hợp nó độc đáo

Nếu bạn có thể nhập một gói, bạn có thể truy cập các tài nguyên trong gói đó. [Nguồn]

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417 đã trở thành một phần của thư viện chuẩn trong Python 3. 7. Tuy nhiên, trên các phiên bản Python cũ hơn, một cổng sau có sẵn dưới dạng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
421. Để sử dụng backport, hãy cài đặt nó từ PyPI

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
12

Backport tương thích với Python 2. 7 cũng như Python 3. 4 và các phiên bản mới hơn

Có một yêu cầu khi sử dụng

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417. các tệp tài nguyên của bạn phải có sẵn bên trong một gói thông thường. Gói không gian tên không được hỗ trợ. Trong thực tế, điều này có nghĩa là tệp phải nằm trong thư mục chứa tệp
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
66

Ví dụ đầu tiên, giả sử bạn có tài nguyên bên trong một gói như thế này

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
13

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
66 chỉ là một tệp trống cần thiết để chỉ định
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
425 như một gói thông thường

Sau đó, bạn có thể sử dụng

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
426 và
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
427 để mở tệp văn bản và tệp nhị phân tương ứng

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
14

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
426 và
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
427 tương đương với
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
430 tích hợp với tham số
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
431 được đặt lần lượt là
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
432 và
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
433. Các chức năng thuận tiện để đọc văn bản hoặc tệp nhị phân trực tiếp cũng có sẵn như
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
434 và
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
435. Xem tài liệu chính thức để biết thêm thông tin

Ghi chú. Để liên tục quay lại sử dụng backport trên các phiên bản Python cũ hơn, bạn có thể nhập

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417 như sau

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
15

Xem phần mẹo và thủ thuật của hướng dẫn này để biết thêm thông tin

Phần còn lại của phần này sẽ hiển thị một số ví dụ phức tạp về việc sử dụng tệp tài nguyên trong thực tế

Loại bỏ các quảng cáo

Thí dụ. Sử dụng tệp dữ liệu

Là một ví dụ đầy đủ hơn về việc sử dụng tệp dữ liệu, bạn sẽ thấy cách triển khai chương trình đố vui dựa trên dữ liệu dân số của Liên hợp quốc. Đầu tiên, tạo gói

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
437 và tải xuống
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
438 từ trang web của Liên hợp quốc

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
16

Mở tệp CSV và xem dữ liệu

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
17

Mỗi dòng chứa dân số của một quốc gia trong một năm nhất định và một biến thể nhất định, cho biết loại kịch bản nào được sử dụng để chiếu. Tệp chứa các dự báo dân số cho đến năm 2100

Hàm sau đọc tệp này và chọn ra tổng dân số của mỗi quốc gia cho một

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
439 và
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
440 nhất định

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
18

Các dòng được đánh dấu cho biết cách sử dụng

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417 để mở tệp dữ liệu. Để biết thêm thông tin về cách làm việc với tệp CSV, hãy xem Đọc và ghi tệp CSV bằng Python

Hàm trên trả về một từ điển có số dân

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
19

Bạn có thể thực hiện bất kỳ điều thú vị nào với từ điển dân số này, bao gồm phân tích và trực quan hóa. Tại đây, bạn sẽ tạo một trò chơi đố vui yêu cầu người dùng xác định quốc gia nào trong nhóm đông dân nhất. Chơi trò chơi sẽ giống như thế này

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
30

Các chi tiết của việc triển khai nằm quá xa chủ đề của hướng dẫn này, vì vậy chúng sẽ không được thảo luận ở đây. Tuy nhiên, bạn có thể mở rộng phần bên dưới để xem mã nguồn hoàn chỉnh

Mã nguồn của bài kiểm tra dân sốHiển thị/Ẩn

Bài kiểm tra dân số bao gồm hai chức năng, một chức năng đọc dữ liệu dân số như bạn đã làm ở trên và một chức năng chạy bài kiểm tra thực tế

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
31

Lưu ý rằng ở dòng 24, bạn cũng kiểm tra xem ________ 2442 có nhỏ hơn ________ 2443 không. Các vị trí có

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
442 trong số
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
443 trở lên không phải là quốc gia thích hợp, mà là các tập hợp như
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
446,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
447, v.v.

Example. Thêm biểu tượng vào GUI Tkinter

When building graphical user interfaces [GUIs], you often need to include resource files like icons. Ví dụ sau đây cho thấy cách bạn có thể làm điều đó bằng cách sử dụng

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417. Ứng dụng cuối cùng sẽ trông khá cơ bản, nhưng nó sẽ có biểu tượng tùy chỉnh cũng như hình minh họa trên nút Tạm biệt

Ví dụ sử dụng Tkinter, một gói GUI có sẵn trong thư viện chuẩn. Nó dựa trên hệ thống cửa sổ Tk, ban đầu được phát triển cho ngôn ngữ lập trình Tcl. Có nhiều gói GUI khác có sẵn cho Python. If you’re using a different one, then you should be able add icons to your app using ideas similar to the ones presented here

Trong Tkinter, hình ảnh được xử lý bởi lớp

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
449. To create a
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
449, you pass in a path to an image file

Remember, when distributing your package, you’re not even guaranteed that resource files will exist as physical files on the file system.

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417 giải quyết vấn đề này bằng cách cung cấp
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
452. Hàm này sẽ trả về đường dẫn đến tệp tài nguyên, tạo tệp tạm thời nếu cần

To make sure any temporary files are cleaned up properly, you should use

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
452 as a context manager using the keyword
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
454

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
32

For the full example, assume you have the following file hierarchy

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
33

If you want to try the example yourself, then you can download these files along with the rest of the source code used in this tutorial by clicking the link below

Lấy mã nguồn. Nhấp vào đây để lấy mã nguồn mà bạn sẽ sử dụng để tìm hiểu về hệ thống nhập Python trong hướng dẫn này

The code is stored in a file with the special name

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
455. This name indicates that the file is the entry point for the package. Having a
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
455 file allows your package to be executed with
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
457

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
34

For more information on calling a package with

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
458, see How to Publish an Open-Source Python Package to PyPI

The GUI is defined in a class called

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
459. Note that you use
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417 to obtain the path of the image files

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
35

If you want to learn more about building GUIs with Tkinter, then check out Python GUI Programming With Tkinter. The official documentation also has a nice list of resources to start with, and the tutorial at TkDocs is another great resource that shows how to use Tk in other languages

Note. One source of confusion and frustration when working with images in Tkinter is that you must make sure the images aren’t garbage collected. Due to the way Python and Tk interact, the garbage collector in Python [at least in CPython] doesn’t register that images are used by

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
461 and
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
462

To make sure that the images are kept around, you should manually add a reference to them. You can see examples of this in the code above on lines 18 and 31

Loại bỏ các quảng cáo

Nhập động

Một trong những tính năng xác định của Python là nó là một ngôn ngữ rất năng động. Mặc dù đôi khi đó là một ý tưởng tồi, nhưng bạn có thể thực hiện nhiều việc với chương trình Python khi nó đang chạy, bao gồm thêm thuộc tính vào lớp, xác định lại phương thức hoặc thay đổi chuỗi tài liệu của mô-đun. For instance, you can change

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
463 so that it doesn’t do anything

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
36

Về mặt kỹ thuật, bạn không định nghĩa lại

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
463. Thay vào đó, bạn đang xác định một
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
463 khác che khuất cái tích hợp sẵn. To return to using the original
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
463, you can delete your custom one with
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
467. If you’re so inclined, you can shadow any Python object that is built into the interpreter

Note. In the above example, you redefine

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
463 using a lambda function. You also could have used a normal function definition

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
37

To learn more about lambda functions, see How to Use Python Lambda Functions

In this section, you’ll learn how to do dynamic imports in Python. With them, you won’t have to decide what to import until your program is running

Using
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
469

So far, you’ve used Python’s

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
44 keyword to import modules and packages explicitly. However, the whole import machinery is available in the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
469 package, and this allows you to do your imports more dynamically. The following script asks the user for the name of a module, imports that module, and prints its docstring

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
38

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
472 trả về một đối tượng mô-đun mà bạn có thể liên kết với bất kỳ biến nào. Then you can treat that variable as a regularly imported module. You can use the script like this

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
39

In each case, the module is imported dynamically by

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
472

Example. Factory Method With Namespace Packages

Think back to the serializers example from earlier. With

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
181 implemented as a namespace package, you had the ability to add custom serializers. In the original example from a previous tutorial, the serializers were made available through a serializer factory. Using
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
469, you can do something similar

Add the following code to your local

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
181 namespace package

>>> import math
>>> math.pi
3.141592653589793
30

The

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
477 factory can create serializers dynamically based on the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
478 parameter, and
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
479 can then apply the serializer to any object that implements a
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
180 method

The factory makes some strong assumptions about the naming of both the module and the class containing the individual serializers. Trong phần tiếp theo, bạn sẽ tìm hiểu về kiến ​​trúc plugin cho phép linh hoạt hơn

You can now re-create the earlier example as follows

>>>

>>> import math
>>> math.pi
3.141592653589793
31

In this case, you no longer need to explicitly import each serializer. Instead, you specify the name of a serializer with a string. The string could even be chosen by your user at runtime

Note. In a regular package, you probably would have implemented

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
477 and
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
479 in an
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
66 file. That would have allowed you to simply import
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
181 and then call
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
485

Tuy nhiên, các gói không gian tên không được phép sử dụng

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
66, vì vậy bạn cần triển khai các chức năng này trong một mô-đun riêng biệt để thay thế

The final example shows that you also get a decent error message if you try to serialize to a format that hasn’t been implemented

Loại bỏ các quảng cáo

Example. A Package of Plugins

Let’s look at another example of using dynamic imports. You can use the following module to set up a flexible plugin architecture in your code. This is similar to the previous example, in which you could plug in serializers for different formats by adding new modules

One application that uses plugins effectively is the Glue exploratory visualization tool. Glue can read many different data formats out of the box. However, if your data format isn’t supported, then you can write your own custom data loader

You do this by adding a function that you decorate and place in a special location to make it easy for Glue to find. You don’t need to alter any part of the Glue source code. See the documentation for all the details

You can set up a similar plugin architecture that you can use in your own projects. Trong kiến ​​trúc, có hai cấp độ

  1. A plugin package is a collection of related plugins corresponding to a Python package
  2. A plugin is a custom behavior made available in a Python module

Mô-đun

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
487 hiển thị kiến ​​trúc plugin có các chức năng sau

>>> import math
>>> math.pi
3.141592653589793
32

The factory functions are used to conveniently add functionality to plugin packages. You’ll see some examples of how they’re used shortly

Looking at all the details of this code is outside the scope of this tutorial. If you’re interested, then you can see an implementation by expanding the section below

Complete Source Code of plugins. pyShow/Hide

The following code shows the implementation of

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
488 described above

>>> import math
>>> math.pi
3.141592653589793
33

This implementation is a bit simplified. In particular, it doesn’t do any explicit error handling. Check out the PyPlugs project for a more complete implementation

Bạn có thể thấy rằng

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
489 sử dụng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
490 để tải động các plugin. Additionally,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
491 uses
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
492 to list all available plugins in a given package

Let’s look at some examples of how to use plugins. The first example is a

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
493 package that you can use to add many different greetings to your app. Kiến trúc plugin đầy đủ chắc chắn là quá mức cần thiết cho ví dụ này, nhưng nó cho thấy cách thức hoạt động của các plugin

Assume you have the following

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
493 package

>>> import math
>>> math.pi
3.141592653589793
34

Mỗi mô-đun

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
493 xác định một hàm nhận một đối số
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
159. Note how they’re all registered as plugins using the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
497 decorator

>>> import math
>>> math.pi
3.141592653589793
35

To learn more about decorators and how they’re used, check out Primer on Python Decorators

Ghi chú. Để đơn giản hóa việc khám phá và nhập plugin, tên của mỗi plugin dựa trên tên của mô-đun chứa nó thay vì tên chức năng. Điều này hạn chế bạn chỉ có một plugin cho mỗi tệp

Để hoàn tất việc thiết lập

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
493 dưới dạng gói plugin, bạn có thể sử dụng các chức năng ban đầu trong
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
487 để thêm chức năng cho chính gói
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
493

>>> import math
>>> math.pi
3.141592653589793
36

Bây giờ bạn có thể sử dụng

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
101 và
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
102 như sau

>>>

>>> import math
>>> math.pi
3.141592653589793
37

Lưu ý rằng

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
101 tự động phát hiện tất cả các plugin có sẵn trong gói

You can also more dynamically choose which plugin to call. Trong ví dụ sau, bạn chọn ngẫu nhiên plugin. However, you could also select a plugin based on a configuration file or user input

>>>

>>> import math
>>> math.pi
3.141592653589793
38

To discover and call the different plugins, you need to import them. Let’s have a quick look at how

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
487 handles imports. The main work is done in the following two functions inside
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
488

>>> import math
>>> math.pi
3.141592653589793
39

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
489 trông có vẻ đơn giản. It uses
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
469 to import a module. But there are a couple of things also happening in the background

  1. Python’s import system ensures that each plugin is imported only once
  2. >>> import math
    >>> dir[]
    ['__annotations__', '__builtins__', ..., 'math']
    
    >>> dir[math]
    ['__doc__', ..., 'nan', 'pi', 'pow', ...]
    
    497 decorators defined inside each plugin module register each imported plugin
  3. In a full implementation, there would also be some error handling to deal with missing plugins

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
491 discovers all the plugins within a package. Here’s how it works

  1. >>> import math
    >>> dir[]
    ['__annotations__', '__builtins__', ..., 'math']
    
    >>> dir[math]
    ['__doc__', ..., 'nan', 'pi', 'pow', ...]
    
    110 from
    >>> import math
    >>> dir[]
    ['__annotations__', '__builtins__', ..., 'math']
    
    >>> dir[math]
    ['__doc__', ..., 'nan', 'pi', 'pow', ...]
    
    417 lists all the files inside a package
  2. The results are filtered to find potential plugins
  3. Each Python file not starting with an underscore is imported
  4. Plugins in any of the files are discovered and registered

Let’s end this section with a final version of the serializers namespace package. One outstanding issue was that the

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
477 factory made strong assumptions about the naming of the serializer classes. You can make this more flexible using plugins

First, add a line registering each of the serializers. Here is an example of how it’s done in the

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
197 serializer

>>> import math
>>> math.pi
3.141592653589793
70

Tiếp theo, cập nhật

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
114 để sử dụng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
487

>>> import math
>>> math.pi
3.141592653589793
71

You implement

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
477 using
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
117 since that will automatically instantiate each serializer. With this refactoring, the serializers work just the same as earlier. However, you have more flexibility in naming your serializer classes

For more information about using plugins, check out PyPlugs on PyPI and the Plug-ins. Adding Flexibility to Your Apps presentation from PyCon 2019

Loại bỏ các quảng cáo

The Python Import System

You’ve seen many ways to take advantage of Python’s import system. In this section, you’ll learn a bit more about what happens behind the scenes as modules and packages are imported

As with most parts of Python, the import system can be customized. You’ll see several ways that you can change the import system, including automatically downloading missing packages from PyPI and importing data files as if they were modules

Import Internals

The details of the Python import system are described in the official documentation. At a high level, three things happen when you import a module [or package]. The module is

  1. Searched for
  2. Loaded
  3. Bound to a namespace

For the usual imports—those done with the

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
44 statement—all three steps happen automatically. When you use
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
469, however, only the first two steps are automatic. You need to bind the module to a variable or namespace yourself

For instance, the following methods of importing and renaming

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
53 are roughly equivalent

>>>

>>> import math
>>> math.pi
3.141592653589793
72

Of course, in normal code you should prefer the former

One thing to note is that, even when you import only one attribute from a module, the whole module is loaded and executed. The rest of the contents of the module just aren’t bound to the current namespace. One way to prove this is to have a look at what’s known as the module cache

>>>

>>> import math
>>> math.pi
3.141592653589793
73

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
121 acts as a module cache. It contains references to all modules that have been imported

The module cache plays a very important role in the Python import system. The first place Python looks for modules when doing an import is in

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
121. If a module is already available, then it isn’t loaded again

This is a great optimization, but it’s also a necessity. If modules were reloaded each time they were imported, then you could end up with inconsistencies in certain situations, such as when the underlying source code changes while a script is running

Recall the import path you saw earlier. It essentially tells Python where to search for modules. However, if Python finds a module in the module cache, then it won’t bother searching the import path for the module

Example. Singletons as Modules

In object-oriented programming, a singleton is a class with at most one instance. While it’s possible to implement singletons in Python, most good uses of singletons can be handled by modules instead. You can trust the module cache to instantiate a class only once

Ví dụ: hãy quay lại dữ liệu dân số của Liên hợp quốc mà bạn đã xem trước đó. The following module defines a class wrapping the population data

>>> import math
>>> math.pi
3.141592653589793
74

Reading the data from disk takes some time. Since you don’t expect the data file to change, you instantiate the class when you load the module. The name of the class starts with an underscore to indicate to users that they shouldn’t use it

You can use the

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
123 singleton to create a Matplotlib graph showing the population projection for the most populous countries

>>>

>>> import math
>>> math.pi
3.141592653589793
75

This creates a chart like the following

Note that loading the data at import time is a kind of antipattern. Ideally, you want your imports to be as free of side effects as possible. A better approach would be to load the data lazily when you need it. You can do this quite elegantly using properties. Expand the following section to see an example

Lazily Loading Population DataShow/Hide

The lazy implementation of

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
124 stores the population data in
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
125 the first time it’s read. The
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
126 property handles this caching of data

>>> import math
>>> math.pi
3.141592653589793
76

Now the data won’t be loaded at import time. Instead, it’ll be imported the first time you access the

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
127 dictionary. Để biết thêm thông tin về các thuộc tính và khái niệm tổng quát hơn về bộ mô tả, hãy xem Bộ mô tả Python. An Introduction

Loại bỏ các quảng cáo

Reloading Modules

The module cache can be a little frustrating when you’re working in the interactive interpreter. It’s not trivial to reload a module after you change it. For example, take a look at the following module

>>> import math
>>> math.pi
3.141592653589793
77

Là một phần của quá trình thử nghiệm và gỡ lỗi mô-đun này, bạn nhập nó vào bảng điều khiển Python

>>>

>>> import math
>>> math.pi
3.141592653589793
78

Let’s say you realize that you have a bug in your code, so you update the

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
128 file in your editor

>>> import math
>>> math.pi
3.141592653589793
79

Returning to your console, you import the updated module to see the effect of your fix

>>>

>>> import math
>>> math.pi
3.141592653589793
78

Why is the answer still

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
129? The module cache is doing its [now frustrating] magic. since Python imported
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
130 earlier, it sees no reason to load the module again even though you just changed it

The most straightforward solution to this is to exit the Python console and restart it. This forces Python to clear its module cache as well

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
01

However, restarting the interpreter isn’t always feasible. You might be in a more complicated session that has taken you a long time to set up. If that’s the case, then you can use

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
131 to reload a module instead

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
02

Note that

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
132 requires a module object, not a string like
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
472 does. Also, be aware that
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
132 has some caveats. Cụ thể, các biến tham chiếu đến các đối tượng trong một mô-đun không bị ràng buộc lại với các đối tượng mới khi mô-đun đó được tải lại. See the documentation for more details

Finders and Loaders

You saw earlier that creating modules with the same name as standard libraries can create problems. For example, if you have a file named

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
135 in Python’s import path, then you won’t be able to import
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 from the standard library

This isn’t always the case, though. Create a file named

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
137 with the following content

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
03

Next, open a Python interpreter and import this new module

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
04

Something weird happened. It doesn’t seem like Python imported your new

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
138 module. Instead, it imported the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
138 module from the standard library. Why are the standard library modules behaving inconsistently? You can get a hint by inspecting the modules

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
05

You can see that

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 is imported from a file, whereas
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
138 is some kind of built-in module. It seems that built-in modules aren’t shadowed by local ones

Note. The built-in modules are compiled into the Python interpreter. Typically, they’re foundational modules like

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
142,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
143, and
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
138. Which modules are built in depends on your Python interpreter, but you can find their names in
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
145

Let’s dig even deeper into Python’s import system. This will also show why built-in modules aren’t shadowed by local ones. There are several steps involved when importing a module

  1. Python checks if the module is available in the module cache. If

    >>> import math
    >>> dir[]
    ['__annotations__', '__builtins__', ..., 'math']
    
    >>> dir[math]
    ['__doc__', ..., 'nan', 'pi', 'pow', ...]
    
    121 contains the name of the module, then the module is already available, and the import process ends

  2. Python starts looking for the module using several finders. A finder will search for the module using a given strategy. The default finders can import built-in modules, frozen modules, and modules on the import path

  3. Python loads the module using a loader. Which loader Python uses is determined by the finder that located the module and is specified in something called a module spec

You can extend the Python import system by implementing your own finder and, if necessary, your own loader. You’ll see a more useful example of a finder later. For now, you’ll learn how to do basic [and possibly silly] customizations of the import system

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
147 controls which finders are called during the import process

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
06

First, note that this answers the question from earlier. built-in modules aren’t shadowed by local modules because the built-in finder is called before the import path finder, which finds local modules. Second, note that you can customize

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
147 to your liking

To quickly mess up your Python session, you can remove all finders

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
07

Vì không có công cụ tìm, Python không thể tìm hoặc nhập các mô-đun mới. However, Python can still import modules that are already in the module cache since it looks there before calling any finders

In the example above,

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
469 was already loaded under the hood before you cleared the list of finders. If you really want to make your Python session completely unusable, then you can also clear the module cache,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
121

The following is a slightly more useful example. You’ll write a finder that prints a message to the console identifying the module being imported. The example shows how to add your own finder, although it doesn’t actually attempt to find a module

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
08

All finders must implement a

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
151 class method, which should try to find a given module. There are three ways that
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
151 can terminate

  1. By returning
    >>> import math
    >>> dir[]
    ['__annotations__', '__builtins__', ..., 'math']
    
    >>> dir[math]
    ['__doc__', ..., 'nan', 'pi', 'pow', ...]
    
    153 if it doesn’t know how to find and load the module
  2. By returning a module spec specifying how to load the module
  3. By raising a
    >>> import math
    >>> dir[]
    ['__annotations__', '__builtins__', ..., 'math']
    
    >>> dir[math]
    ['__doc__', ..., 'nan', 'pi', 'pow', ...]
    
    183 to indicate that the module can’t be imported

The

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
155 prints a message to the console and then explicitly returns
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
153 to indicate that other finders should figure out how to actually import the module

Note. Since Python implicitly returns

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
153 from any function or method without an explicit
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
158, you can leave out line 9. However, in this case it’s good to include
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
159 to make it clear that
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
155 doesn’t find a module

By inserting

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
155 first in the list of finders, you get a running list of all modules being imported

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
09

You can, for instance, see that importing

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
162 triggers the import of several other modules that
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
162 depends on. Note that the verbose option to the Python interpreter,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
164, gives the same information and much, much more

For another example, say that you’re on a quest to rid the world of regular expressions. [Now, why would you want such a thing? Regular expressions are great. ] You could implement the following finder that bans the

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
165 regular expressions module

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
20

Raising a

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
183 ensures that no finder later in the list of finders will be executed. This effectively stops you from using regular expressions in Python

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
21

Even though you’re importing only

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
162, that module is importing
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
165 behind the scenes, so an error is raised

Example. Automatically Install From PyPI

Because the Python import system is already quite powerful and useful, there are many more ways to mess it up than there are to extend it in a useful way. However, the following example can be useful in certain situations

The Python Package Index [PyPI] is your one-stop cheese shop for finding third-party modules and packages. It’s also the place from which

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
155 downloads packages

In other Real Python tutorials, you may have seen instructions to use

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
170 to install the third-party modules and packages you need for following along with examples. Wouldn’t it be great to have Python automatically install missing modules for you?

Warning. In most cases, it really wouldn’t be great to have Python install modules automatically. For instance, in most production settings you want to stay in control of your environment. Furthermore, the documentation cautions against using

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
155 this way

To avoid messing up your Python installation, you should play with this code only in environments that you wouldn’t mind deleting or reinstalling

The following finder attempts to install modules using

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
155

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
22

Compared to the finders you saw earlier, this one is slightly more complicated. By putting this finder last in the list of finders, you know that if you call

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
173, then the module won’t be found on your system. The job of
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
151 is therefore just to do the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
175. If the installation works, then the module spec will be created and returned

Try to use the

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
176 library without installing it yourself

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
23

Thông thường,

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
177 sẽ tăng một
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
183, nhưng trong trường hợp này,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
176 được cài đặt và nhập

While the

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
173 seemingly works, there are some challenges with this approach. One major problem is that the import name of a module doesn’t always correspond to its name on PyPI. For example, the Real Python feed reader is called
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
181 on PyPI, but the import name is simply
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
182

Using

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
173 to import and install
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
182 ends up installing the wrong package

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
24

This could have disastrous consequences for your project

One situation in which automatic installations can be quite helpful is when you’re running Python in the cloud with more limited control over your environment, such as when you’re running Jupyter-style notebooks at Google Colaboratory. Môi trường sổ ghi chép Colab rất phù hợp để thực hiện khám phá dữ liệu hợp tác

Một sổ ghi chép điển hình đi kèm với nhiều gói khoa học dữ liệu được cài đặt, bao gồm NumPy, Pandas và Matplotlib và bạn có thể thêm các gói mới bằng

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
155. But you can also activate automatic installation

Since

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
186 isn’t available locally on the Colab server, the code is copied into the first cell of the notebook

Example. Import Data Files

The final example in this section is inspired by Aleksey Bilogur’s great blog post Import Almost Anything in Python. An Intro to Module Loaders and Finders. You’ve already seen how to use

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417 to import datafiles. Here, you’ll instead implement a custom loader that can import a CSV file directly

Earlier, you worked with a huge CSV file with population data. To make the custom loader example more manageable, consider the following smaller

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
188 file

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
25

The first line is a header naming three fields, and the following two rows of data each contain information about an employee. For more information about working with CSV files, check out Reading and Writing CSV Files in Python

Your goal in this section is to write a finder and a loader that allow you to import the CSV file directly so that you can write code like the following

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
26

The job of the finder will be to search for and recognize CSV files. The loader’s job will be to import the CSV data. Often, you can implement finders and corresponding loaders in one common class. That’s the approach you’ll take here

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
27

There’s quite a bit of code in this example. Luckily, most of the work is done in

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
151 and
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
190. Let’s look at them in more detail

As you saw earlier,

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
151 is responsible for finding the module. In this case, you’re looking for CSV files, so you create a filename with a
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
192 suffix.
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
159 contains the full name of the module that is imported. For example, if you use
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
194, then
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
159 will be
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
196. In this case, the filename will be
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
188

For top-level imports,

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
198 will be
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
153. In that case, you look for the CSV file in the full import path, which will include the current working directory. If you’re importing a CSV file within a package, then
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
198 will be set to the path or paths of the package. If you find a matching CSV file, then a module spec is returned. This module spec tells Python to load the module using
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
301

The CSV data is loaded by

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
190. You can use
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
303 from the standard library to do the actual parsing of the file. Like most things in Python, modules are backed by dictionaries. By adding the CSV data to
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
304, you make it available as attributes of the module

For instance, adding

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
305 to the module dictionary on line 44 allows you to list the field names in the CSV file as follows

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
28

In general, CSV field names can contain spaces and other characters that aren’t allowed in Python attribute names. Before adding the fields as attributes on the module, you sanitize the field names using a regular expression. This is done in

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
306 starting on line 51

You can see an example of this effect in the

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
307 field name above. If you look at the original CSV file, then you’ll see that the header says
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
308 with a space instead of an underscore

By hooking this

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
301 into the Python import system, you get a fair bit of functionality for free. For example, the module cache will make sure that the data file is loaded only once

Import Tips and Tricks

To round out this tutorial, you’ll see a few tips about how to handle certain situations that come up from time to time. You’ll see how to deal with missing packages, cyclical imports, and even packages stored inside ZIP files

Handle Packages Across Python Versions

Sometimes you need to deal with packages that have different names depending on the Python version. You’ve already seen one example of this.

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417 has only been available since Python 3. 7. In earlier versions of Python, you need to install and use
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
421 instead

As long as the different versions of the package are compatible, you can handle this by renaming the package with

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
312

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
15

In the rest of the code, you can refer to

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
313 and not worry about whether you’re using
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417 or
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
421

Normally, it’s easiest to use a

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
153 statement to figure out which version to use. Another option is to inspect the version of the Python interpreter. However, this may add some maintenance cost if you need to update the version numbers

Bạn có thể viết lại ví dụ trước như sau

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
00

This would use

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417 on Python 3. 7 and newer while falling back to
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
421 on older versions of Python. See the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
319 project for good and future-proof advice on how to check which Python version is running

Handle Missing Packages. Use an Alternative

The following use case is closely related to the previous example. Assume there’s a compatible reimplementation of a package. The reimplementation is better optimized, so you want to use it if it’s available. However, the original package is more easily available and also delivers acceptable performance

One such example is

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
320, which is an optimized version of
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
321 from the standard library. You can handle these preferences the same way you handled different package names earlier

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
01

This will use

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
320 if it’s available and fall back to
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
321 if not

Another similar example is the UltraJSON package, an ultrafast JSON encoder and decoder that can be used as a replacement for

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
196 in the standard library

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
02

By renaming

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
325 to
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
196, you don’t have to worry about which package was actually imported

Handle Missing Packages. Use a Mock Instead

A third, related example is adding a package that provides a nice-to-have feature that’s not strictly necessary for your app. Again, this can be solved by adding

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
153 to your imports. The extra challenge is how you will replace the optional package if it’s not available

For a concrete example, say that you’re using Colorama to add colored text in the console. Colorama mainly consists of special string constants that add color when printed

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
03

Unfortunately, the color doesn’t render in the example above. In your terminal it’ll look something like this

Before you start using Colorama colors, you should call

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
328. Setting
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
329 to
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
330 means that the color directives will be automatically reset at the end of the string. It’s a useful setting if you want to color just one line at a time

If you’d rather have all your output be [for example] blue, then you can let

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
329 be
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
332 and add
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
333 to the beginning of your script. The following colors are available

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
04

You can also use

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
334 to control the style of your text. You can choose between
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
335,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
336, and
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
337

Finally,

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
338 provides codes for controlling the position of the cursor. You can use it to display the progress or status of a running script. The following example displays a countdown from
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
339

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
05

Note how the counter stays in place instead of printing on separate lines as it normally would

Let’s get back to the task at hand. For many applications, adding color to your console output is cool but not critical. To avoid adding yet another dependency to your app, you want to use Colorama only if it’s available on the system and not break the app if it isn’t

To do this, you can take inspiration from testing and its use of mocks. A mock can substitute for another object while allowing you to control its behavior. Here’s a naïve attempt at mocking Colorama

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
06

This doesn’t quite work, because

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
340 is represented by a string that messes up your output. Instead, you want to create an object that always renders as the empty string

It’s possible to change the return value of

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
177 on
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
342 objects. Tuy nhiên, trong trường hợp này, sẽ thuận tiện hơn nếu bạn viết bản mô phỏng của riêng mình

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
07

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
343 is an empty string that will also return the empty string when it’s called. This effectively gives us a reimplementation of Colorama, just without the colors

The final trick is that

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
344 returns itself, so that all colors, styles, and cursor movements that are attributes on
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
345,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
346,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
347, and
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
348 are mocked as well

The

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
349 module is designed to be a drop-in replacement for Colorama, so you can update the countdown example using search and replace

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
08

If you run this script on a system in which Colorama isn’t available, then it’ll still work, but it may not look as nice

With Colorama installed, you should see the same results as earlier

Nhập tập lệnh dưới dạng mô-đun

Một điểm khác biệt giữa tập lệnh và mô-đun thư viện là tập lệnh thường làm một việc gì đó, trong khi thư viện cung cấp chức năng. Cả tập lệnh và thư viện đều nằm trong các tệp Python thông thường và đối với Python, không có sự khác biệt nào giữa chúng

Thay vào đó, sự khác biệt là ở chỗ tệp được sử dụng như thế nào. nó nên được thực thi với

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
350 hay được nhập với
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
351 bên trong một tập lệnh khác?

Đôi khi, bạn sẽ có một mô-đun hoạt động như cả tập lệnh và thư viện. Bạn có thể thử cấu trúc lại mô-đun của mình thành hai tệp khác nhau

Một ví dụ về điều này trong thư viện tiêu chuẩn là gói

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
196. Bạn thường sử dụng nó như một thư viện, nhưng nó cũng đi kèm với một tập lệnh có thể chỉnh sửa các tệp JSON. Giả sử bạn có tệp
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
353 sau

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
09

Vì JSON thường chỉ được đọc bởi máy móc nên nhiều tệp JSON không được định dạng theo kiểu có thể đọc được. Trên thực tế, việc các tệp JSON bao gồm một dòng văn bản rất dài là điều khá phổ biến.

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
354 là tập lệnh sử dụng thư viện
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
196 để định dạng JSON theo cách dễ đọc hơn

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
10

Bây giờ cấu trúc của tệp JSON trở nên dễ nắm bắt hơn nhiều. Bạn có thể sử dụng tùy chọn

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
356 để sắp xếp các khóa theo thứ tự bảng chữ cái

Mặc dù việc chia nhỏ tập lệnh và thư viện là một phương pháp hay, nhưng Python có một thành ngữ giúp có thể coi một mô-đun vừa là tập lệnh vừa là thư viện cùng một lúc. Như đã lưu ý trước đó, giá trị của biến mô-đun

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
125 đặc biệt được đặt trong thời gian chạy dựa trên việc mô-đun được nhập hay chạy dưới dạng tập lệnh

Hãy thử nghiệm nó. Tạo tập tin sau

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
11

Nếu bạn chạy tệp này, thì bạn sẽ thấy rằng

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
125 được đặt thành giá trị đặc biệt
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
126

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
12

However, if you import the module, then

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
125 is set to the name of the module

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
13

This behavior is leveraged in the following pattern

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
14

Let’s use this in a bigger example. In an attempt to keep you young, the following script will replace any “old” age [

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
361 or above] with
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
129

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
15

You can run this as a script, and it will interactively make the age you type younger

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
16

You can also use the module as an importable library. The

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
124 test on line 12 makes sure that there are no side effects when you import the library. Only the functions
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
364 and
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
365 are defined. You can, for instance, use this library as follows

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
17

Without the protection of the

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
124 test, the import would have triggered the interactive
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
367 and made
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
368 very hard to use as a library

Run Python Scripts From ZIP Files

A slightly obscure feature of Python is that it can run scripts packaged into ZIP files. The main advantage of this is that you can distribute a full package as a single file

Note, however, that this still requires Python to be installed on the system. If you want to distribute your Python application as a stand-alone executable file, then see Using PyInstaller to Easily Distribute Python Applications

If you give the Python interpreter a ZIP file, then it’ll look for a file named

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
455 inside the ZIP archive, extract it, and run it. As a basic example, create the following
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
455 file

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
18

This will print a message when you run it

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
19

Now add it to a ZIP archive. You may be able to do this on the command line

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
20

On Windows, you can instead use point and click. Select the file in the File Explorer, then right-click and select Send to → Compressed [zipped] folder

Since

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
126 isn’t a very descriptive name, you named the ZIP file
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
372. You can now call it directly with Python

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
21

Lưu ý rằng tập lệnh của bạn biết rằng nó nằm bên trong

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
372. Furthermore, the root of your ZIP file is added to Python’s import path so that your scripts can import other modules inside the same ZIP file

Think back to the earlier example in which you created a quiz based on population data. It’s possible to distribute this whole application as a single ZIP file.

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417 will make sure the data file is extracted from the ZIP archive when it’s needed

The app consists of the following files

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
22

You could add these to a ZIP file in the same way you did above. However, Python comes with a tool called

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
375 that streamlines the process of packing applications into ZIP archives. You use it as follows

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
23

This command essentially does two things. it creates an entry point and packages your application

Remember that you needed a

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
455 file as an entry point inside your ZIP archive. If you supply the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
458 option with information about how your app should be started, then
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
375 creates this file for you. In this example, the generated
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
455 looks like this

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
24

This

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
455 is packaged, along with the contents of the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
381 directory, into a ZIP archive named
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
382. The
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
383 suffix signals that this is a Python file wrapped into a ZIP archive

Note. By default,

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
375 doesn’t compress any files. It only packages them into a single file. You can tell
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
375 to compress the files as well by adding the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
386 option

However, this feature is available only in Python 3. 7 and later. See the

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
375 documentation for more information

On Windows,

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
383 files should already be registered as Python files. On Mac and Linux, you can have
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
375 create executable files by using the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
390 interpreter option and specifying which interpreter to use

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
25

The

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
390 option adds a shebang [
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
392] that tells the operating system how to run the file. Additionally, it makes the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
383 file executable so that you can run the file just by typing its name

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
26

Notice the

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
394 in front of the filename. This is a typical trick on Mac and Linux to run executable files in the current directory. If you move the file to a directory on your
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
395, or if you’re using Windows, then you should be able to use only the filename.
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
382

Note. On Python 3. 6 and older, the previous command will fail with a message saying that it couldn’t find the population data resource in the

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
437 directory. This is due to a limitation in
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
398

A workaround is to supply the absolute path to

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
382. On Mac and Linux, you can do this with the following trick

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
27

Lệnh

>>> import math
>>> math.pi
3.141592653589793
300 mở rộng đến đường dẫn của thư mục hiện tại

Let’s close this section by looking at a nice effect of using

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417. Hãy nhớ rằng bạn đã sử dụng đoạn mã sau để mở tệp dữ liệu

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
28

A more common way to open data files is to locate them based on your module’s

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
413 attribute

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
29

Cách tiếp cận này thường hoạt động tốt. However, it falls apart when your application is packed into a ZIP file

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
30

Your data file is inside the ZIP archive, so

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
430 isn’t able to open it.
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417, on the other hand, will extract your data to a temporary file before opening it

Handle Cyclical Imports

A cyclical import happens when you have two or more modules importing each other. Cụ thể hơn, hãy tưởng tượng rằng mô-đun

>>> import math
>>> math.pi
3.141592653589793
305 sử dụng
>>> import math
>>> math.pi
3.141592653589793
306 và mô-đun
>>> import math
>>> math.pi
3.141592653589793
307 nhập khẩu tương tự
>>> import math
>>> math.pi
3.141592653589793
305

Hệ thống nhập của Python ở một mức độ nào đó được thiết kế để xử lý các chu kỳ nhập. For instance, the following code—while not very useful—runs fine

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
31

Cố gắng nhập

>>> import math
>>> math.pi
3.141592653589793
305 trong trình thông dịch tương tác cũng nhập
>>> import math
>>> math.pi
3.141592653589793
307

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
32

Lưu ý rằng

>>> import math
>>> math.pi
3.141592653589793
307 được nhập vào giữa quá trình nhập của
>>> import math
>>> math.pi
3.141592653589793
305, chính xác tại câu lệnh
>>> import math
>>> math.pi
3.141592653589793
306 trong mã nguồn của
>>> import math
>>> math.pi
3.141592653589793
305. Lý do điều này không kết thúc trong đệ quy vô tận là người bạn cũ của chúng tôi bộ đệm mô-đun

Khi bạn nhập

>>> import math
>>> math.pi
3.141592653589793
315, một tham chiếu đến
>>> import math
>>> math.pi
3.141592653589793
305 sẽ được thêm vào bộ nhớ cache của mô-đun ngay cả trước khi tải
>>> import math
>>> math.pi
3.141592653589793
305. Khi
>>> import math
>>> math.pi
3.141592653589793
307 cố gắng nhập
>>> import math
>>> math.pi
3.141592653589793
305 sau đó, nó chỉ cần sử dụng tham chiếu trong bộ đệm mô-đun

Bạn cũng có thể có các mô-đun làm điều gì đó hữu ích hơn một chút. Nếu bạn xác định các thuộc tính và chức năng trong các mô-đun của mình, thì tất cả vẫn hoạt động

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
33

Nhập

>>> import math
>>> math.pi
3.141592653589793
305 hoạt động giống như trước đây

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
32

Các sự cố liên quan đến nhập đệ quy bắt đầu xuất hiện khi bạn thực sự sử dụng mô-đun khác tại thời điểm nhập thay vì chỉ xác định các hàm sẽ sử dụng mô-đun khác sau này. Thêm một dòng vào

>>> import math
>>> math.pi
3.141592653589793
321

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
35

Bây giờ Python bị nhầm lẫn khi nhập

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
36

Thông báo lỗi lúc đầu có vẻ hơi khó hiểu. Nhìn lại mã nguồn, bạn có thể xác nhận rằng

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
130 được định nghĩa trong mô-đun
>>> import math
>>> math.pi
3.141592653589793
305

Vấn đề là

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
130 không được xác định trong
>>> import math
>>> math.pi
3.141592653589793
305 tại thời điểm
>>> import math
>>> math.pi
3.141592653589793
307 được nhập. Do đó,
>>> import math
>>> math.pi
3.141592653589793
327 được sử dụng bởi lệnh gọi tới
>>> import math
>>> math.pi
3.141592653589793
328

Thêm vào sự nhầm lẫn, bạn sẽ không gặp vấn đề gì khi nhập

>>> import math
>>> math.pi
3.141592653589793
307

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
37

Vào thời điểm

>>> import math
>>> math.pi
3.141592653589793
307 gọi
>>> import math
>>> math.pi
3.141592653589793
328,
>>> import math
>>> math.pi
3.141592653589793
305 được nhập đầy đủ và
>>> import math
>>> math.pi
3.141592653589793
327 được xác định rõ. Cuối cùng, do bộ đệm mô-đun mà bạn đã thấy trước đó,
>>> import math
>>> math.pi
3.141592653589793
315 có thể hoạt động nếu bạn thực hiện một số thao tác nhập khác trước

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
38

Vậy làm thế nào bạn có thể tránh bị sa lầy và bối rối bởi việc nhập khẩu theo chu kỳ?

Thông thường, thời gian dễ dàng nhất để khắc phục các lần nhập theo chu kỳ là trước khi bạn triển khai chúng. Nếu bạn thấy các chu kỳ trong bản phác thảo kiến ​​trúc của mình, hãy xem xét kỹ hơn và cố gắng phá vỡ các chu kỳ đó

Tuy nhiên, đôi khi việc giới thiệu một chu kỳ nhập khẩu là hợp lý. Như bạn đã thấy ở trên, đây không phải là vấn đề miễn là các mô-đun của bạn chỉ định nghĩa các thuộc tính, hàm, lớp, v.v. Mẹo thứ hai—cũng là một phương pháp thiết kế tốt—là giữ cho các mô-đun của bạn không có tác dụng phụ khi nhập

Nếu bạn thực sự cần các mô-đun có chu kỳ nhập và tác dụng phụ, thì vẫn còn một cách khác. thực hiện nhập cục bộ của bạn bên trong các chức năng

Lưu ý rằng trong đoạn mã sau,

>>> import math
>>> math.pi
3.141592653589793
306 được thực hiện bên trong
>>> import math
>>> math.pi
3.141592653589793
328. Điều này có hai hậu quả. Đầu tiên,
>>> import math
>>> math.pi
3.141592653589793
307 chỉ khả dụng bên trong hàm
>>> import math
>>> math.pi
3.141592653589793
328. Quan trọng hơn, quá trình nhập không xảy ra cho đến khi bạn gọi
>>> import math
>>> math.pi
3.141592653589793
328 sau khi
>>> import math
>>> math.pi
3.141592653589793
305 đã được nhập đầy đủ

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
39

Bây giờ không có vấn đề gì khi nhập và sử dụng

>>> import math
>>> math.pi
3.141592653589793
305

>>>

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
40

Lưu ý rằng trên thực tế,

>>> import math
>>> math.pi
3.141592653589793
307 không được nhập cho đến khi bạn gọi
>>> import math
>>> math.pi
3.141592653589793
328. Để có một góc nhìn khác về nhập khẩu theo chu kỳ, hãy xem ghi chú kinh điển của Fredrik Lundh

Nhập hồ sơ

Một mối quan tâm khi nhập một số mô-đun và gói là nó sẽ thêm vào thời gian khởi động tập lệnh của bạn. Tùy thuộc vào ứng dụng của bạn, điều này có thể hoặc không quan trọng

Kể từ khi phát hành Python 3. 7, bạn đã có một cách nhanh chóng để biết cần bao nhiêu thời gian để nhập các gói và mô-đun. Trăn 3. 7 hỗ trợ tùy chọn dòng lệnh

>>> import math
>>> math.pi
3.141592653589793
344, đo lường và in lượng thời gian mỗi mô-đun cần để nhập

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
41

Cột

>>> import math
>>> math.pi
3.141592653589793
345 hiển thị thời gian nhập tích lũy [tính bằng micrô giây] trên cơ sở từng gói. Bạn có thể đọc danh sách như sau. Python đã dành
>>> import math
>>> math.pi
3.141592653589793
346 micro giây để nhập đầy đủ
>>> import math
>>> math.pi
3.141592653589793
347, bao gồm cả việc nhập
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
138,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 và triển khai C
>>> import math
>>> math.pi
3.141592653589793
350

Cột

>>> import math
>>> math.pi
3.141592653589793
351 hiển thị thời gian cần thiết để chỉ nhập mô-đun đã cho, không bao gồm mọi lần nhập đệ quy. Bạn có thể thấy rằng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
138 mất
>>> import math
>>> math.pi
3.141592653589793
353 micro giây để nhập,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 mất
>>> import math
>>> math.pi
3.141592653589793
355,
>>> import math
>>> math.pi
3.141592653589793
350 mất
>>> import math
>>> math.pi
3.141592653589793
357 và bản thân việc nhập
>>> import math
>>> math.pi
3.141592653589793
347 mất
>>> import math
>>> math.pi
3.141592653589793
359 micro giây. Nói chung, điều này làm tăng thêm thời gian tích lũy là
>>> import math
>>> math.pi
3.141592653589793
346 micro giây [trong phạm vi lỗi làm tròn]

Hãy xem ví dụ về

>>> import math
>>> math.pi
3.141592653589793
361 từ phần Colorama

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
42

Trong ví dụ này, việc nhập

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
349 mất gần 0. 013 giây. Hầu hết thời gian đó được dành để nhập Colorama và các phụ thuộc của nó. Cột
>>> import math
>>> math.pi
3.141592653589793
351 hiển thị thời gian nhập không bao gồm nhập lồng nhau

Đối với một ví dụ cực đoan, hãy xem xét đơn lẻ

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
124 từ trước đó. Vì nó đang tải một tệp dữ liệu lớn nên nhập cực kỳ chậm. Để kiểm tra điều này, bạn có thể chạy
>>> import math
>>> math.pi
3.141592653589793
365 dưới dạng tập lệnh với tùy chọn
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
386

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
43

Trong trường hợp này, mất gần 2 giây để nhập

>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
124, trong đó khoảng 1. 6 giây được sử dụng trong chính mô-đun, chủ yếu để tải tệp dữ liệu

>>> import math
>>> math.pi
3.141592653589793
344 là một công cụ tuyệt vời để tối ưu hóa quá trình nhập của bạn. Nếu bạn cần theo dõi tổng quát hơn và tối ưu hóa mã của mình, thì hãy xem Hàm hẹn giờ Python. Ba cách để theo dõi mã của bạn

Sự kết luận

Trong hướng dẫn này, bạn đã biết hệ thống nhập Python. Giống như nhiều thứ trong Python, nó khá đơn giản để sử dụng cho các tác vụ cơ bản như nhập mô-đun và gói. Đồng thời, hệ thống nhập khẩu khá phức tạp, linh hoạt và có thể mở rộng. Bạn đã học được một số thủ thuật liên quan đến nhập mà bạn có thể tận dụng trong mã của riêng mình

Trong hướng dẫn này, bạn đã học cách

  • Tạo các gói không gian tên
  • Nhập tài nguyên và tệp dữ liệu
  • Quyết định những gì cần nhập động trong thời gian chạy
  • Mở rộng hệ thống nhập của Python
  • Xử lý các phiên bản khác nhau của gói

Trong suốt hướng dẫn, bạn đã thấy nhiều liên kết đến thông tin thêm. Nguồn có thẩm quyền nhất trên hệ thống nhập Python là tài liệu chính thức

  • Hệ thống nhập khẩu
  • Gói
    >>> import math
    >>> dir[]
    ['__annotations__', '__builtins__', ..., 'math']
    
    >>> dir[math]
    ['__doc__', ..., 'nan', 'pi', 'pow', ...]
    
    469
  • PEP 420. Gói không gian tên ẩn
  • Nhập mô-đun

Bạn có thể sử dụng kiến ​​thức về nhập Python của mình bằng cách làm theo các ví dụ trong hướng dẫn này. Nhấp vào liên kết bên dưới để truy cập vào mã nguồn

Lấy mã nguồn. Nhấp vào đây để lấy mã nguồn mà bạn sẽ sử dụng để tìm hiểu về hệ thống nhập Python trong hướng dẫn này

Đánh dấu là đã hoàn thành

🐍 Thủ thuật Python 💌

Nhận một Thủ thuật Python ngắn và hấp dẫn được gửi đến hộp thư đến của bạn vài ngày một lần. Không có thư rác bao giờ. Hủy đăng ký bất cứ lúc nào. Được quản lý bởi nhóm Real Python

Gửi cho tôi thủ thuật Python »

Giới thiệu về Geir Arne Hjelle

Geir Arne là một Pythonista cuồng nhiệt và là thành viên của nhóm hướng dẫn Real Python

» Thông tin thêm về Geir Arne

Mỗi hướng dẫn tại Real Python được tạo bởi một nhóm các nhà phát triển để nó đáp ứng các tiêu chuẩn chất lượng cao của chúng tôi. Các thành viên trong nhóm đã làm việc trong hướng dẫn này là

Aldren

Brad

Đan

Joanna

Gia-cốp

Bậc thầy Kỹ năng Python trong thế giới thực Với quyền truy cập không giới hạn vào Python thực

Tham gia với chúng tôi và có quyền truy cập vào hàng nghìn hướng dẫn, khóa học video thực hành và cộng đồng các Pythonistas chuyên gia

Nâng cao kỹ năng Python của bạn »

Bậc thầy Kỹ năng Python trong thế giới thực
Với quyền truy cập không giới hạn vào Python thực

Tham gia với chúng tôi và có quyền truy cập vào hàng ngàn hướng dẫn, khóa học video thực hành và cộng đồng Pythonistas chuyên gia

Nâng cao kỹ năng Python của bạn »

Bạn nghĩ sao?

Đánh giá bài viết này

Tweet Chia sẻ Chia sẻ Email

Bài học số 1 hoặc điều yêu thích mà bạn đã học được là gì?

Mẹo bình luận. Những nhận xét hữu ích nhất là những nhận xét được viết với mục đích học hỏi hoặc giúp đỡ các sinh viên khác. Nhận các mẹo để đặt câu hỏi hay và nhận câu trả lời cho các câu hỏi phổ biến trong cổng thông tin hỗ trợ của chúng tôi

Chủ Đề