Python phân tích thông điệp var/log

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 sử dụng 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 đang 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 thế 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. Technically, a package is a Python module with an

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

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

Note that a package is still a module. As a user, you usually don’t need to worry about whether you’re importing a module or a package

In practice, a package typically corresponds to a file directory containing Python files and other directories. To create a Python package yourself, you create a directory and a file named

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
66 inside it. The
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
66 file contains the contents of the package when it’s treated as a module. It can be left empty

Note. Directories without an

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
66 file are still treated as packages by Python. However, these won’t be regular packages, but something called namespace packages. You’ll learn more about them later

In general, submodules and subpackages aren’t imported when you import a package. However, you can use

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
66 to include any or all submodules and subpackages if you want. To show a few examples of this behavior, you’ll create a package for saying
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
70 in a few different languages. The package will consist of the following directories and files

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

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

Each country file prints out a greeting, while the

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
66 files selectively import some of the subpackages and submodules. The exact contents of the files are as follows

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

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

Note that

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
72 imports only
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

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

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
75 doesn’t import anything, while
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

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

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
78 but not
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
79. Each country module will print a greeting when it’s imported

Let’s play with the

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
80 package at the interactive prompt to get a better understanding of how the subpackages and submodules behave

>>>

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

When

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
74 is imported, the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
83 modules are imported as well. You can see this because the country modules print a greeting when they’re imported

>>>

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

The

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
75 file is empty. This means that importing the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
85 package creates the namespace but has no other effect

>>>

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

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

Remember, importing a module both loads the contents and creates a namespace containing the contents. The last few examples show that it’s possible for the same module to be part of different namespaces

Technical Detail. The module namespace is implemented as a Python dictionary and is available at the

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

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

>>>

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

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

You rarely need to interact with

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

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

Similarly, Python’s global namespace is also a dictionary. You can access it through

>>> 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ự

Relative imports must be in the form

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
92, and the location you’re importing from must start with a dot

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

Python’s Import Path

How does Python find the modules and packages it imports? You’ll see more details about the mechanics of the Python import system later. For now, just know that Python looks for modules and packages in its import path. This is a list of locations that are searched for modules to import

Note. When you type

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
99, Python will look for
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
100 a few different places before searching the import path

In particular, it’ll look in a module cache to see if

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
100 has already been imported, and it’ll search among the built-in modules

You’ll learn more about the full Python import machinery in a later section

You can inspect Python’s import path by printing

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
102. Broadly speaking, this list will contain three different kinds of locations

  1. The directory of the current script [or the current directory if there’s no script, such as when Python is running interactively]
  2. The contents of the
    >>> import math
    >>> dir[]
    ['__annotations__', '__builtins__', ..., 'math']
    
    >>> dir[math]
    ['__doc__', ..., 'nan', 'pi', 'pow', ...]
    
    103 environment variable
  3. Other, installation-dependent directories

Typically, Python will start at the beginning of the list of locations and look for a given module in each location until the first match. Since the script directory or the current directory is always first in this list, you can make sure that your scripts find your self-made modules and packages by organizing your directories and being careful about which directory you run Python from

However, you should also be careful that you don’t create modules that shadow, or hide, other important modules. As an example, say that you define the following

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

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

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

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

Using this module works as expected

>>>

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

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

But this module also shadows the

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 module that’s included in the standard library. Unfortunately, that means our earlier example of looking up the value of π no longer works

>>>

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

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

The problem is that Python now searches your new

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

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
50 instead of searching the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 module in the standard library

To avoid these kinds of issues, you should be careful with the names of your modules and packages. In particular, your top-level module and package names should be unique. If

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 is defined as a submodule within a package, then it won’t shadow the built-in module

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

Example. Structure Your Imports

While it’s possible to organize your imports by using the current directory as well as by manipulating

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

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
102, the process is often unruly and prone to errors. To see a typical example, consider the following application

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

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

The app will re-create a given file structure by creating directories and empty files. The

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
112 file contains the main script, and
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
113 is a library module with a few functions for dealing with files. The following is an example of output from the app, in this case by running it in the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

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

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

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

The two source code files as well as the automatically created

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
115 file are re-created inside a new directory named
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

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

Now take a look at the source code. The main functionality of the app is defined in

>>> 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

In lines 12 to 16, you read a root path from the command line. In the above example you use a dot, which means the current directory. This path will be used as the

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
118 of the file hierarchy that you’ll re-create

The actual work happens in lines 19 to 23. First, you create a unique path,

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
119, that will be the root of your new file hierarchy. Then you loop through all paths below the original
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
118 and re-create them as empty files inside the new file hierarchy

For manipulating paths like this,

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
121 in the standard library is quite useful. For more details on how it’s used, check out Python 3’s
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
121 Module. Taming the File System

On line 26, you call

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
123. You’ll learn more about the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
124 test on line 25 later. For now, you should know that the special variable
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
125 has the value
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
126 inside scripts, but it gets the name of the module inside imported modules. For more information on
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
125, check out Defining Main Functions in Python and What Does if name == “main” Do in Python?

Note that you import

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
128 on line 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 uses a counter to find a path that doesn’t already exist. In the app, you use it to find a unique subdirectory to use as the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
119 of the re-created file hierarchy. Next,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
131 makes sure all necessary directories are created before creating an empty file using
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

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

Have a look at the import of

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

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

>>> 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, điều này sẽ 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 nên 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 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

Trong 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

The problem is that relative imports are resolved differently in scripts than are imported modules. 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 nhiều đến 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 vấn đề phức tạp 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

You might have code that you want to both run on its own and import from other scripts. In that case, it’s usually worthwhile to refactor your code so that you split the common part into a library module

While it’s a good idea to separate scripts and libraries, all Python files can be both executed and imported. 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 pháp 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ộ tuần tự hóa này có một chút hạn chế, nhưng nó sẽ đủ để chứng minh cách thức hoạt động của các gói không gian tên

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

Note. You might get a

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

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
184 when running the code yourself. Đ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 cần 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 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. Separating imports from within your package gives you some overview over the internal dependencies of your code

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 một định nghĩa hàm như thế nào để phá vỡ các chu kỳ nhập

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 quyền truy cập vào tài nguyên trong các gói được cung cấp. 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ế. By reusing the import system, you get a more consistent way of dealing with the files inside your packages. It also gives you easier access to resource files in other packages. 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 sẵn 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 các 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 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

The details of the implementation are too far outside the topic of this tutorial, so they won’t be discussed here. 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.

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

Khi xây dựng giao diện người dùng đồ họa [GUI], bạn thường cần bao gồm các tệp tài nguyên như biểu tượng. 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. Nếu bạn đang sử dụng một biểu tượng khác, thì bạn có thể thêm các biểu tượng vào ứng dụng của mình bằng các ý tưởng tương tự như những ý tưởng được trình bày ở đây

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. Để tạo một
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
449, bạn chuyển vào một đường dẫn đến một tệp hình ảnh

Hãy nhớ rằng, khi phân phối gói của bạn, bạn thậm chí không được đảm bảo rằng các tệp tài nguyên sẽ tồn tại dưới dạng tệp vật lý trên hệ thống tệp.

>>> 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

Để đảm bảo mọi tệp tạm thời được dọn sạch đúng cách, bạn nên sử dụng

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
452 làm trình quản lý ngữ cảnh bằng từ khóa
>>> 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

Đối với ví dụ đầy đủ, giả sử bạn có hệ thống phân cấp tệp sau

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

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

Nếu bạn muốn tự mình thử ví dụ, thì bạn có thể tải xuống các tệp này cùng với phần còn lại của mã nguồn được sử dụng trong hướng dẫn này bằng cách nhấp vào liên kết 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

Mã được lưu trữ trong một tệp có tên đặc biệt

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
455. Tên này chỉ ra rằng tệp là điểm vào cho gói. Có tệp
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
455 cho phép gói của bạn được thực thi với
>>> 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

Để biết thêm thông tin về cách gọi gói bằng

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
458, hãy xem Cách xuất bản Gói Python nguồn mở lên PyPI

GUI được định nghĩa trong một lớp có tên là

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
459. Lưu ý rằng bạn sử dụng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417 để lấy đường dẫn của tệp hình ảnh

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

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

Nếu bạn muốn tìm hiểu thêm về cách xây dựng GUI với Tkinter, hãy xem Lập trình GUI Python với Tkinter. Tài liệu chính thức cũng có một danh sách tài nguyên hay để bắt đầu và hướng dẫn tại TkDocs là một tài nguyên tuyệt vời khác cho biết cách sử dụng Tk trong các ngôn ngữ khác

Ghi chú. Một nguyên nhân gây nhầm lẫn và thất vọng khi làm việc với hình ảnh trong Tkinter là bạn phải đảm bảo hình ảnh không được thu gom rác. Do cách Python và Tk tương tác, trình thu gom rác trong Python [ít nhất là trong CPython] không đăng ký rằng hình ảnh được sử dụng bởi

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

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

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

Để đảm bảo rằng hình ảnh được lưu giữ xung quanh, bạn nên thêm tham chiếu đến chúng theo cách thủ công. Bạn có thể xem các ví dụ về điều này trong đoạn mã trên ở dòng 18 và 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. Chẳng hạn, bạn có thể thay đổi ________ 2463 để nó không làm gì cả

>>>

>>> 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. Để quay lại sử dụng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
463 ban đầu, bạn có thể xóa tùy chỉnh của mình bằng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
467. Nếu muốn, bạn có thể tạo bóng cho bất kỳ đối tượng Python nào được tích hợp trong trình thông dịch

Ghi chú. Trong ví dụ trên, bạn xác định lại

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
463 bằng hàm lambda. Bạn cũng có thể đã sử dụng một định nghĩa chức năng bình thường

>>>

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

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

Để tìm hiểu thêm về các hàm lambda, hãy xem Cách sử dụng các hàm Lambda của Python

Trong phần này, bạn sẽ học cách nhập động trong Python. Với chúng, bạn sẽ không phải quyết định nhập nội dung gì cho đến khi chương trình của bạn đang chạy

Sử dụng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

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

Cho đến giờ, bạn đã sử dụng từ khóa

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
44 của Python để nhập các mô-đun và gói một cách rõ ràng. Tuy nhiên, toàn bộ máy móc nhập khẩu có sẵn trong gói
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
469 và điều này cho phép bạn thực hiện việc nhập khẩu của mình linh hoạt hơn. Đoạn script sau hỏi người dùng tên của một mô-đun, nhập mô-đun đó và in chuỗi tài liệu của nó

>>> 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. Sau đó, bạn có thể coi biến đó là một mô-đun được nhập thường xuyên. Bạn có thể sử dụng kịch bản như thế này

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

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

Trong mỗi trường hợp, mô-đun được nhập động bởi

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

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

Thí dụ. Phương thức xuất xưởng với các gói không gian tên

Nghĩ lại ví dụ serializer từ trước đó. Với

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
181 được triển khai dưới dạng gói không gian tên, bạn có khả năng thêm các bộ nối tiếp tùy chỉnh. Trong ví dụ ban đầu từ hướng dẫn trước, các bộ nối tiếp được cung cấp thông qua một nhà máy sản xuất bộ nối tiếp. Sử dụng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
469, bạn có thể làm điều gì đó tương tự

Thêm mã sau vào gói không gian tên

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
181 cục bộ của bạn

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

Nhà máy

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
477 có thể tự động tạo bộ nối tiếp dựa trên tham số
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
478 và sau đó,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
479 có thể áp dụng bộ nối tiếp cho bất kỳ đối tượng nào triển khai phương thức
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

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

Nhà máy đưa ra một số giả định mạnh mẽ về cách đặt tên của cả mô-đun và lớp chứa các bộ nối tiếp riêng lẻ. 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

Bây giờ bạn có thể tạo lại ví dụ trước đó như sau

>>>

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

Trong trường hợp này, bạn không cần phải nhập rõ ràng từng bộ nối tiếp nữa. Thay vào đó, bạn chỉ định tên của bộ nối tiếp bằng một chuỗi. Chuỗi thậm chí có thể được chọn bởi người dùng của bạn khi chạy

Ghi chú. Trong một gói thông thường, bạn có thể đã triển khai

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

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
479 trong tệp
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
66. Điều đó sẽ cho phép bạn chỉ cần nhập
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
181 và sau đó gọi
>>> 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 thay thế

Ví dụ cuối cùng cho thấy rằng bạn cũng nhận được một thông báo lỗi khá rõ ràng nếu bạn cố gắng tuần tự hóa thành một định dạng chưa được triển khai

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

Thí dụ. Một gói plugin

Hãy xem một ví dụ khác về việc sử dụng nhập động. You can use the following module to set up a flexible plugin architecture in your code. Điều này tương tự như ví dụ trước, trong đó bạn có thể cắm các bộ nối tiếp cho các định dạng khác nhau bằng cách thêm các mô-đun mới

Một ứng dụng sử dụng plugin hiệu quả là công cụ trực quan hóa khám phá Keo. Keo có thể đọc được nhiều định dạng dữ liệu khác nhau. Tuy nhiên, nếu định dạng dữ liệu của bạn không được hỗ trợ, thì bạn có thể viết trình tải dữ liệu tùy chỉnh của riêng mình

Bạn làm điều này bằng cách thêm một chức năng mà bạn trang trí và đặt ở một vị trí đặc biệt để Keo dễ dàng tìm thấy. Bạn không cần thay đổi bất kỳ phần nào của mã nguồn Keo. Xem tài liệu để biết tất cả các chi tiết

You can set up a similar plugin architecture that you can use in your own projects. Within the architecture, there are two levels

  1. Gói plugin là tập hợp các plugin có liên quan tương ứng với gói Python
  2. Plugin là một hành vi tùy chỉnh có sẵn trong mô-đun Python

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

Các chức năng của nhà máy được sử dụng để thêm chức năng vào các gói plugin một cách thuận tiện. Bạn sẽ thấy một số ví dụ về cách chúng được sử dụng trong thời gian ngắn

Xem xét tất cả các chi tiết của mã này nằm ngoài phạm vi của hướng dẫn này. Nếu quan tâm, bạn có thể xem triển khai bằng cách mở rộng phần bên dưới

Mã nguồn hoàn chỉnh của plugin. pyHiện/Ẩn

Đoạn mã sau cho thấy việc triển khai

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
488 được mô tả ở trên

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

Việc triển khai này được đơn giản hóa một chút. 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. Ngoài ra,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
492 để liệt kê tất cả các plugin có sẵn trong một gói nhất định

Hãy xem xét một số ví dụ về cách sử dụng plugin. Ví dụ đầu tiên là gói

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
493 mà bạn có thể sử dụng để thêm nhiều lời chào khác nhau vào ứng dụng của mình. 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

Giả sử bạn có gói

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

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

>>> 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. Lưu ý cách tất cả chúng được đăng ký làm plugin bằng trình trang trí
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

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

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

Để tìm hiểu thêm về các công cụ trang trí và cách chúng được sử dụng, hãy xem 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 hàm. Đ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

Bạn cũng có thể linh hoạt hơn trong việc chọn plugin để gọi. Trong ví dụ sau, bạn chọn ngẫu nhiên plugin. Tuy nhiên, bạn cũng có thể chọn plugin dựa trên tệp cấu hình hoặc đầu vào của người dùng

>>>

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

Để khám phá và gọi các plugin khác nhau, bạn cần nhập chúng. Hãy xem nhanh cách

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
487 giao dịch hàng nhập khẩu. Công việc chính được thực hiện ở hai chức năng sau bên trong
>>> 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. Nó sử dụng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
469 để nhập một mô-đun. Nhưng có một vài điều cũng xảy ra trong nền

  1. Hệ thống nhập Python đảm bảo rằng mỗi plugin chỉ được nhập một lần
  2. >>> import math
    >>> dir[]
    ['__annotations__', '__builtins__', ..., 'math']
    
    >>> dir[math]
    ['__doc__', ..., 'nan', 'pi', 'pow', ...]
    
    497 trình trang trí được xác định bên trong mỗi mô-đun plugin đăng ký từng plugin đã nhập
  3. Trong quá trình triển khai đầy đủ, cũng sẽ có một số xử lý lỗi để xử lý các plugin bị thiếu

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
491 khám phá tất cả các plugin trong một gói. Đây là cách nó hoạt động

  1. >>> import math
    >>> dir[]
    ['__annotations__', '__builtins__', ..., 'math']
    
    >>> dir[math]
    ['__doc__', ..., 'nan', 'pi', 'pow', ...]
    
    110 từ
    >>> import math
    >>> dir[]
    ['__annotations__', '__builtins__', ..., 'math']
    
    >>> dir[math]
    ['__doc__', ..., 'nan', 'pi', 'pow', ...]
    
    417 liệt kê tất cả các tệp bên trong một gói
  2. Các kết quả được lọc để tìm các plugin tiềm năng
  3. Mỗi tệp Python không bắt đầu bằng dấu gạch dưới được nhập
  4. Các plugin trong bất kỳ tệp nào được phát hiện và đăng ký

Hãy kết thúc phần này với phiên bản cuối cùng của gói không gian tên serializer. Một vấn đề nổi bật là nhà máy

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
477 đã đưa ra các giả định mạnh mẽ về việc đặt tên cho các lớp bộ nối tiếp. Bạn có thể làm cho điều này linh hoạt hơn bằng cách sử dụng plugin

Đầu tiên, thêm một dòng đăng ký từng bộ nối tiếp. Đây là một ví dụ về cách nó được thực hiện trong bộ nối tiếp

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

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

>>> 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

Bạn triển khai

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
477 bằng cách sử dụng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
117 vì điều đó sẽ tự động khởi tạo từng bộ nối tiếp. Với việc tái cấu trúc này, các bộ nối tiếp hoạt động giống như trước đây. Tuy nhiên, bạn có thể linh hoạt hơn trong việc đặt tên cho các lớp serializer của mình

Để biết thêm thông tin về cách sử dụng plugin, hãy xem PyPlugs trên PyPI và các Trình cắm. Thêm tính linh hoạt vào bản trình bày Ứng dụng của bạn từ PyCon 2019

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

Hệ thống nhập Python

You’ve seen many ways to take advantage of Python’s import system. Trong phần này, bạn sẽ tìm hiểu thêm một chút về những gì diễn ra ở hậu trường khi các mô-đun và gói được nhập

Như với hầu hết các phần của Python, hệ thống nhập có thể được tùy chỉnh. Bạn sẽ thấy một số cách mà bạn có thể thay đổi hệ thống nhập, bao gồm tự động tải xuống các gói bị thiếu từ PyPI và nhập các tệp dữ liệu như thể chúng là các mô-đun

Nhập nội bộ

Chi tiết về hệ thống nhập Python được mô tả trong tài liệu chính thức. Ở cấp độ cao, có ba điều xảy ra khi bạn nhập một mô-đun [hoặc gói]. mô-đun là

  1. Tìm kiếm
  2. Nạp vào
  3. Bị ràng buộc vào một không gian tên

Đối với các thao tác nhập thông thường—những thao tác được thực hiện với câu lệnh

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
44—cả ba bước diễn ra tự động. Tuy nhiên, khi bạn sử dụng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
469, chỉ có hai bước đầu tiên là tự động. Bạn cần tự liên kết mô-đun với một biến hoặc không gian tên

Chẳng hạn, các phương pháp nhập và đổi tên

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
53 sau đây gần như tương đương

>>>

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

Tất nhiên, trong mã bình thường, bạn nên chọn cái trước

One thing to note is that, even when you import only one attribute from a module, the whole module is loaded and executed. Phần còn lại của nội dung mô-đun không bị ràng buộc với không gian tên hiện tại. Một cách để chứng minh điều này là xem cái được gọi là bộ đệm mô-đun

>>>

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

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
121 hoạt động như một bộ đệm mô-đun. Nó chứa các tham chiếu đến tất cả các mô-đun đã được nhập

Bộ đệm mô-đun đóng một vai trò rất quan trọng trong hệ thống nhập Python. Nơi đầu tiên Python tìm kiếm các mô-đun khi thực hiện nhập là trong

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
121. Nếu một mô-đun đã có sẵn, thì nó không được tải lại

Đây là một tối ưu hóa tuyệt vời, nhưng nó cũng là một điều cần thiết. Nếu các mô-đun được tải lại mỗi khi chúng được nhập, thì bạn có thể gặp phải tình trạng không nhất quán trong một số trường hợp nhất định, chẳng hạn như khi mã nguồn cơ bản thay đổi trong khi tập lệnh đang chạy

Nhớ lại đường dẫn nhập mà bạn đã thấy trước đó. Về cơ bản, nó cho Python biết nơi tìm kiếm các mô-đun. Tuy nhiên, nếu Python tìm thấy một mô-đun trong bộ đệm mô-đun, thì nó sẽ không bận tâm tìm kiếm đường dẫn nhập cho mô-đun

Thí dụ. Singletons như các mô-đun

Trong lập trình hướng đối tượng, một singleton là một lớp có nhiều nhất một thể hiện. Mặc dù có thể triển khai các singleton trong Python, nhưng thay vào đó, hầu hết các cách sử dụng tốt các singleton có thể được xử lý bởi các mô-đun. Bạn có thể tin tưởng bộ đệm mô-đun để khởi tạo một lớp chỉ một lần

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 đó. Mô-đun sau định nghĩa một lớp bao bọc dữ liệu dân số

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

Đọc dữ liệu từ đĩa mất một thời gian. Vì bạn không muốn tệp dữ liệu thay đổi, nên bạn khởi tạo lớp khi bạn tải mô-đun. Tên của lớp bắt đầu bằng dấu gạch dưới để cho người dùng biết rằng họ không nên sử dụng nó

Bạn có thể sử dụng đơn lẻ

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
123 để tạo biểu đồ Matplotlib hiển thị dự báo dân số cho các quốc gia đông dân nhất

>>>

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

Điều này tạo ra một biểu đồ như sau

Lưu ý rằng việc tải dữ liệu tại thời điểm nhập là một loại phản mẫu. Lý tưởng nhất là bạn muốn hàng nhập khẩu của mình không có tác dụng phụ nhất có thể. Cách tiếp cận tốt hơn là tải dữ liệu một cách lười biếng khi bạn cần. Bạn có thể làm điều này khá tao nhã bằng cách sử dụng các thuộc tính. Mở rộng phần sau để xem ví dụ

Tải dữ liệu dân số một cách lười biếngHiển thị/Ẩn

Việc triển khai lười biếng của

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
124 lưu trữ dữ liệu dân số trong
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
125 lần đầu tiên nó được đọc. Thuộc tính
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
126 xử lý bộ đệm dữ liệu này

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

Bây giờ dữ liệu sẽ không được tải khi nhập. Thay vào đó, nó sẽ được nhập vào lần đầu tiên bạn truy cập từ điển

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
127. Để 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. Một lời giới thiệu

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

Tải lại mô-đun

Bộ đệm mô-đun có thể hơi khó chịu khi bạn đang làm việc trong trình thông dịch tương tác. Việc tải lại một mô-đun sau khi bạn thay đổi nó không phải là chuyện nhỏ. Ví dụ: hãy xem mô-đun sau

>>> 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

Giả sử bạn nhận ra rằng bạn có một lỗi trong mã của mình, vì vậy bạn cập nhật tệp

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
128 trong trình chỉnh sửa của mình

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

Quay trở lại bảng điều khiển của bạn, bạn nhập mô-đun đã cập nhật để xem hiệu quả của bản sửa lỗi của bạn

>>>

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

Tại sao câu trả lời vẫn là

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
129? . vì Python đã nhập
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
130 trước đó, nên không có lý do gì để tải lại mô-đun mặc dù bạn vừa thay đổi nó

Giải pháp đơn giản nhất cho vấn đề này là thoát khỏi bảng điều khiển Python và khởi động lại nó. This forces Python to clear its module cache as well

>>>

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

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

Tuy nhiên, khởi động lại trình thông dịch không phải lúc nào cũng khả thi. Bạn có thể đang ở trong một phiên phức tạp hơn khiến bạn mất nhiều thời gian để thiết lập. Nếu đúng như vậy, bạn có thể sử dụng

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
131 để tải lại mô-đun thay thế

>>>

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

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

Lưu ý rằng

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
132 yêu cầu đối tượng mô-đun, không phải chuỗi như
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
472. Ngoài ra, hãy lưu ý rằng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
132 có một số lưu ý. 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. Xem tài liệu để biết thêm chi tiết

Trình tìm và Trình tải

Bạn đã thấy trước đó rằng việc tạo các mô-đun có cùng tên với các thư viện tiêu chuẩn có thể gây ra sự cố. Ví dụ: nếu bạn có tệp có tên

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
135 trong đường dẫn nhập của Python thì bạn sẽ không thể nhập
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

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

Điều này không phải luôn luôn như vậy, mặc dù. Tạo một tệp có tên

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
137 với nội dung sau

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

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

Tiếp theo, mở trình thông dịch Python và nhập mô-đun mới này

>>>

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

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

Một cái gì đó kỳ lạ đã xảy ra. Có vẻ như Python không nhập mô-đun

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
138 mới của bạn. 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

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

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 được nhập từ một tệp, trong khi
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
138 là một loại mô-đun tích hợp sẵn nào đó. Có vẻ như các mô-đun tích hợp không bị che khuất bởi các mô-đun cục bộ

Ghi chú. Các mô-đun tích hợp được biên dịch thành trình thông dịch Python. Thông thường, chúng là các mô-đun nền tảng như

>>> 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 và
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
138. Những mô-đun nào được tích hợp tùy thuộc vào trình thông dịch Python của bạn, nhưng bạn có thể tìm thấy tên của chúng trong
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

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

Hãy tìm hiểu sâu hơn về hệ thống nhập của Python. Điều này cũng sẽ cho thấy lý do tại sao các mô-đun tích hợp không bị che khuất bởi các mô-đun cục bộ. Có một số bước liên quan khi nhập một mô-đun

  1. Python kiểm tra xem mô-đun có sẵn trong bộ đệm mô-đun không. Nếu

    >>> import math
    >>> dir[]
    ['__annotations__', '__builtins__', ..., 'math']
    
    >>> dir[math]
    ['__doc__', ..., 'nan', 'pi', 'pow', ...]
    
    121 chứa tên của mô-đun, thì mô-đun đó đã có sẵn và quá trình nhập kết thúc

  2. Python bắt đầu tìm kiếm mô-đun bằng một số công cụ tìm. Một công cụ tìm sẽ tìm kiếm mô-đun bằng một chiến lược nhất định. Công cụ tìm mặc định có thể nhập các mô-đun tích hợp, mô-đun cố định và mô-đun trên đường dẫn nhập

  3. Python tải mô-đun bằng trình tải. Trình tải nào Python sử dụng được xác định bởi công cụ tìm định vị mô-đun và được chỉ định trong một thứ gọi là thông số mô-đun

Bạn có thể mở rộng hệ thống nhập Python bằng cách triển khai công cụ tìm của riêng bạn và, nếu cần, trình tải của riêng bạn. Bạn sẽ thấy một ví dụ hữu ích hơn về công cụ tìm sau. Hiện tại, bạn sẽ học cách thực hiện các tùy chỉnh cơ bản [và có thể ngớ ngẩn] của hệ thống nhập

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
147 kiểm soát công cụ tìm nào được gọi trong quá trình nhập

>>>

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

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

Đầu tiên, lưu ý rằng điều này trả lời câu hỏi từ trước đó. các mô-đun tích hợp không bị che khuất bởi các mô-đun cục bộ vì công cụ tìm tích hợp được gọi trước công cụ tìm đường dẫn nhập, tìm các mô-đun cục bộ. Thứ hai, lưu ý rằng bạn có thể tùy chỉnh

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
147 theo ý thích của mình

Để nhanh chóng làm rối phiên Python của bạn, bạn có thể xóa tất cả các công cụ tìm

>>>

>>> 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. Tuy nhiên, Python vẫn có thể nhập các mô-đun đã có trong bộ đệm mô-đun vì nó tìm ở đó trước khi gọi bất kỳ công cụ tìm nào

Trong ví dụ trên,

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
469 đã được tải ngầm trước khi bạn xóa danh sách công cụ tìm. Nếu bạn thực sự muốn làm cho phiên Python của mình hoàn toàn không sử dụng được, thì bạn cũng có thể xóa bộ đệm mô-đun,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

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

Sau đây là một ví dụ hữu ích hơn một chút. Bạn sẽ viết một công cụ tìm in thông báo tới bảng điều khiển xác định mô-đun đang được nhập. Ví dụ này cho thấy cách thêm công cụ tìm của riêng bạn, mặc dù nó không thực sự cố gắng tìm một mô-đun

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

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

Tất cả các công cụ tìm phải triển khai một phương thức lớp

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
151, phương thức này sẽ cố gắng tìm một mô-đun nhất định. Có ba cách mà
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
151 có thể chấm dứt

  1. Bằng cách trả lại
    >>> import math
    >>> dir[]
    ['__annotations__', '__builtins__', ..., 'math']
    
    >>> dir[math]
    ['__doc__', ..., 'nan', 'pi', 'pow', ...]
    
    153 nếu nó không biết cách tìm và tải mô-đun
  2. Bằng cách trả về thông số mô-đun chỉ định cách tải mô-đun
  3. Bằng cách tăng
    >>> import math
    >>> dir[]
    ['__annotations__', '__builtins__', ..., 'math']
    
    >>> dir[math]
    ['__doc__', ..., 'nan', 'pi', 'pow', ...]
    
    183 để cho biết rằng không thể nhập mô-đun

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
155 in một thông báo tới bảng điều khiển và sau đó trả về một cách rõ ràng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
153 để chỉ ra rằng những người tìm kiếm khác nên tìm ra cách thực sự nhập mô-đun

Ghi chú. Vì Python hoàn toàn trả về

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
153 từ bất kỳ hàm hoặc phương thức nào mà không có
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
158 rõ ràng, bạn có thể bỏ qua dòng 9. Tuy nhiên, trong trường hợp này, tốt nhất là thêm vào
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
159 để làm rõ rằng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
155 không tìm thấy mô-đun

Bằng cách chèn

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
155 trước vào danh sách công cụ tìm, bạn sẽ có một danh sách đang chạy gồm tất cả các mô-đun đang được nhập

>>>

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

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

Ví dụ: bạn có thể thấy rằng việc nhập

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
162 sẽ kích hoạt việc nhập một số mô-đun khác mà
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
162 phụ thuộc vào. Lưu ý rằng tùy chọn dài dòng cho trình thông dịch Python,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
164, cung cấp thông tin tương tự và nhiều, nhiều hơn nữa

Ví dụ khác, giả sử bạn đang thực hiện nhiệm vụ loại bỏ thế giới của các biểu thức thông thường. [Bây giờ, tại sao bạn lại muốn một thứ như vậy? Cụm từ thông dụng thật tuyệt. ] Bạn có thể triển khai công cụ tìm sau cấm mô-đun biểu thức chính quy

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

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

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

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

Nâng cao một

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
183 đảm bảo rằng không có công cụ tìm nào sau này trong danh sách công cụ tìm sẽ được thực thi. Điều này thực sự ngăn bạn sử dụng các biểu thức thông thường trong Python

>>>

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

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

Mặc dù bạn chỉ đang nhập

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
162, nhưng mô-đun đó đang nhập
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
165 ở hậu trường, vì vậy sẽ xảy ra lỗi

Thí dụ. Tự động cài đặt từ PyPI

Vì hệ thống nhập của Python đã khá mạnh mẽ và hữu ích, nên có nhiều cách để làm rối tung nó hơn là mở rộng nó theo cách hữu ích. Tuy nhiên, ví dụ sau có thể hữu ích trong một số trường hợp

Chỉ mục gói Python [PyPI] là cửa hàng pho mát duy nhất của bạn để tìm các gói và mô-đun của bên thứ ba. Đây cũng là nơi mà các gói tải xuống của

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

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

Trong các hướng dẫn Real Python khác, bạn có thể đã xem hướng dẫn sử dụng

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
170 để cài đặt các mô-đun và gói của bên thứ ba mà bạn cần để làm theo cùng với các ví dụ. Sẽ thật tuyệt nếu Python tự động cài đặt các mô-đun còn thiếu cho bạn phải không?

Cảnh báo. Trong hầu hết các trường hợp, sẽ không tuyệt lắm nếu Python tự động cài đặt các mô-đun. Chẳng hạn, trong hầu hết các cài đặt sản xuất, bạn muốn kiểm soát môi trường của mình. Hơn nữa, tài liệu cảnh báo không nên sử dụng

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
155 theo cách này

Để tránh làm rối cài đặt Python của bạn, bạn chỉ nên sử dụng mã này trong các môi trường mà bạn không ngại xóa hoặc cài đặt lại

Phần sau tìm thấy các nỗ lực cài đặt mô-đun 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', ...]
22

So với các công cụ tìm bạn đã thấy trước đó, công cụ này phức tạp hơn một chút. 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. Nếu quá trình cài đặt hoạt động, thì thông số mô-đun sẽ được tạo và trả về

Cố gắng sử dụng thư viện

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
176 mà không cần tự cài đặt

>>>

>>> 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
>>> 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

Mặc dù

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
173 dường như hoạt động, nhưng có một số thách thức với cách tiếp cận này. Một vấn đề lớn là tên nhập của một mô-đun không phải lúc nào cũng tương ứng với tên của nó trên PyPI. Ví dụ: trình đọc nguồn cấp Python thực có tên là
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
181 trên PyPI, nhưng tên nhập chỉ đơn giản là
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

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

Sử dụng

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
173 để nhập và cài đặt
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
182 kết thúc bằng việc cài đặt sai gói

>>>

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

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

Điều này có thể gây hậu quả tai hại cho dự án của bạn

Một tình huống trong đó cài đặt tự động có thể khá hữu ích là khi bạn đang chạy Python trên đám mây với quyền kiểm soát hạn chế hơn đối với môi trường của bạn, chẳng hạn như khi bạn đang chạy sổ ghi chép kiểu Jupyter tại Google Collaboratory. 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. Nhưng bạn cũng có thể kích hoạt cài đặt tự động

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
186 không có sẵn cục bộ trên máy chủ Colab nên mã được sao chép vào ô đầu tiên của sổ ghi chép

Thí dụ. Nhập tệp dữ liệu

Ví dụ cuối cùng trong phần này được lấy cảm hứng từ bài đăng trên blog tuyệt vời của Aleksey Bilogur Nhập hầu hết mọi thứ bằng Python. Giới thiệu về Trình tải và Trình tìm mô-đun. Bạn đã biết cách sử dụng

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417 để nhập tệp dữ liệu. Tại đây, thay vào đó, bạn sẽ triển khai trình tải tùy chỉnh có thể nhập trực tiếp tệp CSV

Earlier, you worked with a huge CSV file with population data. Để làm cho ví dụ về trình tải tùy chỉnh dễ quản lý hơn, hãy xem xét tệp

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
188 nhỏ hơn sau đây

>>> 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. Bạn đã thấy một ví dụ về điều này.

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417 chỉ khả dụng kể từ Python 3. 7. Trong các phiên bản Python cũ hơn, bạn cần cài đặt và sử dụng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
421 để thay thế

Miễn là các phiên bản khác nhau của gói tương thích, bạn có thể xử lý vấn đề này bằng cách đổi tên gói thành

>>> 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

Trong phần còn lại của mã, bạn có thể tham khảo

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
313 và không cần lo lắng về việc bạn đang sử dụng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

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

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

Thông thường, cách dễ nhất là sử dụng câu lệnh

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
153 để tìm ra phiên bản nào sẽ sử dụng. Một tùy chọn khác là kiểm tra phiên bản của trình thông dịch Python. Tuy nhiên, điều này có thể thêm một số chi phí bảo trì nếu bạn cần cập nhật số phiên bản

You could rewrite the previous example as follows

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

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

Điều này sẽ sử dụng

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417 trên Python 3. 7 trở lên trong khi quay lại
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
421 trên các phiên bản Python cũ hơn. Xem dự án
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
319 để có lời khuyên hữu ích và phù hợp với tương lai về cách kiểm tra phiên bản Python nào đang chạy

Handle Missing Packages. Sử dụng một thay thế

Trường hợp sử dụng sau có liên quan chặt chẽ với ví dụ trước. 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

Một ví dụ như vậy là

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
320, đây là phiên bản được tối ưu hóa của
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
321 từ thư viện chuẩn. 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. However, in this case, it’s more convenient to write your own mock

>>> 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

Import Scripts as Modules

One difference between scripts and library modules is that scripts typically do something, whereas libraries provide functionality. Both scripts and libraries live inside regular Python files, and as far as Python is concerned, there’s no difference between them

Instead, the difference is in how the file is meant to be used. should it be executed with

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
350 or imported with
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
351 inside another script?

Sometimes you’ll have a module that works as both a script and a library. You could try to refactor your module into two different files

One example of this in the standard library is the

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
196 package. You usually use it as a library, but it also comes bundled with a script that can prettify JSON files. Assume you have the following
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

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

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

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

As JSON is often read only by machines, many JSON files aren’t formatted in a readable fashion. 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

While it’s good practice to split scripts and libraries, Python has an idiom that makes it possible to treat a module as both a script and a library at the same time. As noted earlier, the value of the special

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
125 module variable is set at runtime based on whether the module is imported or run as a script

Hãy thử nghiệm nó. Create the following file

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

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

If you run this file, then you’ll see that

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
125 is set to the special value
>>> 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

Note that your script is aware that it lives inside

>>> 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. nó tạo ra một điểm vào và đóng gói ứng dụng của bạn

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

Lưu ý

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
394 trước tên tệp. Đây là một thủ thuật điển hình trên Mac và Linux để chạy các tệp thực thi trong thư mục hiện tại. Nếu bạn di chuyển tệp vào một thư mục trên
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
395 của mình hoặc nếu bạn đang sử dụng Windows thì bạn chỉ có thể sử dụng tên tệp.
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

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

Ghi chú. Trên Python 3. 6 trở lên, lệnh trước đó sẽ không thành công với thông báo nói rằng không thể tìm thấy tài nguyên dữ liệu dân số trong thư mục

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
437. Điều này là do một giới hạn trong
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

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

Một cách giải quyết khác là cung cấp đường dẫn tuyệt đối tới

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
382. Trên Mac và Linux, bạn có thể làm điều này bằng thủ thuật sau

>>> 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

Hãy kết thúc phần này bằng cách xem xét một hiệu ứng tuyệt vời khi sử dụng

>>> 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

Một cách phổ biến hơn để mở tệp dữ liệu là xác định vị trí của chúng dựa trên thuộc tính

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
413 của mô-đun của bạn

>>> 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. Tuy nhiên, nó sẽ bị hỏng khi ứng dụng của bạn được đóng gói thành tệp ZIP

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

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

Tệp dữ liệu của bạn nằm trong kho lưu trữ ZIP nên

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
430 không thể mở tệp đó. Mặt khác,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417 sẽ trích xuất dữ liệu của bạn thành một tệp tạm thời trước khi mở tệp đó

Nhập khẩu theo chu kỳ thương mại

Nhập theo chu kỳ xảy ra khi bạn có hai hoặc nhiều mô-đun nhập lẫn nhau. 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 Python ở một mức độ nào đó được thiết kế để xử lý các chu kỳ nhập. Chẳng hạn, đoạn mã sau—mặc dù không hữu dụng lắm—chạy tốt

>>> 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. Looking back at the source code, you can confirm that

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
130 is defined in the
>>> import math
>>> math.pi
3.141592653589793
305 module

The problem is that

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

>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
130 isn’t defined in
>>> import math
>>> math.pi
3.141592653589793
305 at the time
>>> import math
>>> math.pi
3.141592653589793
307 gets imported. Consequently,
>>> import math
>>> math.pi
3.141592653589793
327 is used by the call to
>>> import math
>>> math.pi
3.141592653589793
328

To add to the confusion, you’ll have no issues importing

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

>>>

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

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

By the time

>>> import math
>>> math.pi
3.141592653589793
307 calls
>>> import math
>>> math.pi
3.141592653589793
328,
>>> import math
>>> math.pi
3.141592653589793
305 is fully imported and
>>> import math
>>> math.pi
3.141592653589793
327 is well defined. As a final twist, because of the module cache you saw earlier,
>>> import math
>>> math.pi
3.141592653589793
315 might work if you do some other imports first

>>>

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

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

So how can you avoid being bogged down and confused by cyclical imports? Having two or more modules importing each other is often a sign that you can improve the design of your modules

Often, the easiest time to fix cyclical imports is before you implement them. 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ỳ đó

Still, there are times when it’s reasonable to introduce an import cycle. As you saw above, this isn’t a problem so long as your modules define only attributes, functions, classes, and so on. The second tip—which is also good design practice—is to keep your modules free of side effects at import time

If you really need modules with import cycles and side effects, there’s still another way out. 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 diễn 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 hoàn toàn

>>> 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ó 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 thực hiện giám sát và tối ưu hóa tổng quát hơn cho mã của mình, hãy xem Hàm hẹn giờ Python. Ba cách để theo dõi mã của bạn

Phần kết luận

Trong hướng dẫn này, bạn đã biết về 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à

Tuổi

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 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ậ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ủ Đề