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. Imports in Python are important for structuring your code effectively. Using imports properly will make you more productive, allowing you to reuse code while keeping your projects maintainableThis tutorial will provide a thorough overview of Python’s
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
44 statement and how it works. The import system is powerful, and you’ll learn how to harness this power. While you’ll cover many of the concepts behind Python’s import system, this tutorial is mostly example driven. You’ll learn from several code examples throughoutIn this tutorial, you’ll learn how to
- Use modules, packages, and namespace packages
- Handle resources and data files inside your packages
- Import modules dynamically at runtime
- Customize Python’s import system
Throughout the tutorial, you’ll see examples of how to play with the Python import machinery in order to work most efficiently. While all the code is shown in the tutorial, you can also download it by clicking the box below
Get the Source Code. Click here to get the source code you’ll use to learn about the Python import system in this tutorial
Basic Python >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
44
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
Python code is organized into both modules and packages. This section will explain how they differ and how you can work with them
Later in the tutorial, you’ll see some advanced and lesser-known uses of Python’s import system. However, let’s get started with the basics. importing modules and packages
Remove adsModules
con trăn. org glossary defines module as follows
An object that serves as an organizational unit of Python code. Modules have a namespace containing arbitrary Python objects. Modules are loaded into Python by the process of importing. [Source]
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ã PythonSức mạnh thực sự của các mô-đun là chúng có thể được nhập và sử dụng lại trong mã khác. Xem xét ví dụ sau
>>>
>>> import math
>>> math.pi
3.141592653589793
Trong dòng đầu tiên,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
48, bạn nhập mã trong mô-đun >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 và cung cấp mã đó để sử dụng. Ở dòng thứ hai, bạn truy cập biến >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
50 trong mô-đun >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49. >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 là một phần của thư viện chuẩn của Python, có nghĩa là nó luôn có sẵn để nhập khi bạn chạy PythonLư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. Namespaces are useful for keeping your code readable and organized. In the words of Tim PetersNamespaces are one honking great idea—let’s do more of those. [Source]
You can list the contents of a namespace with
>>> 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', ...]
Using
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
56 without any argument shows what’s in the global namespace. To see the contents of the >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 namespace, you use >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
59You’ve already seen the most straightforward use of
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
44. However, there are other ways to use it that allow you to import specific parts of a module and to rename the module as you import itThe following code imports only the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
50 variable from the >>> 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', ...]
1Note that this places
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
50 in the global namespace and not within a >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 namespaceYou can also rename modules and attributes as they’re imported
>>>
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
4For more details about the syntax for importing modules, check out Python Modules and Packages – An Introduction
Packages
You can use a package to further organize your modules. con trăn. org glossary defines package as follows
A Python module which can contain submodules or recursively, subpackages. Technically, a package is a Python module with an
65 attribute. [Source]>>> import math >>> dir[] ['__annotations__', '__builtins__', ..., 'math'] >>> dir[math] ['__doc__', ..., 'nan', 'pi', 'pow', ...]
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 emptyNote. 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 laterIn 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', ...]
1Each 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', ...]
3Note 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 importedLet’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
3When
>>> 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
7The
>>> 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', ...]
0Remember, 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', ...]
2You rarely need to interact with
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
86 directlySimilarly, 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', ...]
88It’s fairly common to import subpackages and submodules in an
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
66 file to make them more readily available to your users. You can see one example of this in the popular >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
90 packageRemove adsAbsolute and Relative Imports
Recall the source code of
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
72 in the earlier example>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
0You’ve already seen
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
92 statements such as >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
93, but what does the dot [>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
94] in >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
95 mean?The dot refers to the current package, and the statement is an example of a relative import. You can read it as “From the current package, import the subpackage
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
73. ”There’s an equivalent absolute import statement in which you explicitly name the current package
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
1In fact, all imports in
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
80 could have been done explicitly with similar absolute importsRelative 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 dotThe PEP 8 style guide recommends using absolute imports in general. However, relative imports are an alternative for organizing package hierarchies. For more information, see Absolute vs Relative Imports in 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
Ghi chú. 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 pathIn 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 modulesYou’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- The directory of the current script [or the current directory if there’s no script, such as when Python is running interactively]
- Nội dung của biến môi trường
103>>> import math >>> dir[] ['__annotations__', '__builtins__', ..., 'math'] >>> dir[math] ['__doc__', ..., 'nan', 'pi', 'pow', ...]
- 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
Tuy nhiên, bạn cũng nên cẩn thận rằng bạn không tạo các mô-đun che khuất hoặc ẩn các mô-đun quan trọng khác. Ví dụ, giả sử bạn xác định mô-đun
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 sau>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
2Sử dụng mô-đun này hoạt động như mong đợi
>>>
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
3Nhưng mô-đun này cũng phủ bóng mô-đun
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 có trong thư viện chuẩn. Thật không may, điều đó có nghĩa là ví dụ tra cứu giá trị của π trước đây của chúng tôi không còn hoạt động nữa>>>
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
4Vấn đề là Python hiện tìm kiếm mô-đun
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 mới của bạn cho >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
50 thay vì tìm kiếm mô-đun >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 trong thư viện chuẩnĐể tránh những loại sự cố này, bạn nên cẩn thận với tên của các mô-đun và gói của mình. Cụ thể, tên gói và mô-đun cấp cao nhất của bạn phải là duy nhất. Nếu
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 được định nghĩa là một mô-đun con trong một gói, thì nó sẽ không che khuất mô-đun tích hợpRemove adsThí dụ. Cấu trúc nhập khẩu của bạn
Mặc dù có thể tổ chức quá trình nhập của bạn bằng cách sử dụng thư mục hiện tại cũng như bằng cách thao tác với
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
103 và thậm chí là >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
102, quá trình này thường không theo quy tắc và dễ xảy ra lỗi. Để xem một ví dụ điển hình, hãy xem xét ứng dụng sau>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
5Ứng dụng sẽ tạo lại cấu trúc tệp đã cho bằng cách tạo thư mục và tệp trống. Tệp
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
112 chứa tập lệnh chính và >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
113 là mô-đun thư viện có một số chức năng để xử lý tệp. Sau đây là một ví dụ về đầu ra từ ứng dụng, trong trường hợp này bằng cách chạy nó trong thư mục >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
114>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
6Hai tệp mã nguồn cũng như tệp
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
115 được tạo tự động được tạo lại bên trong một thư mục mới có tên là >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
116Bây giờ hãy xem mã nguồn. Chức năng chính của ứng dụng được xác định trong
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
112>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
7Trong các dòng 12 đến 16, bạn đọc đường dẫn gốc từ dòng lệnh. Trong ví dụ trên bạn sử dụng dấu chấm, có nghĩa là thư mục hiện tại. Đường dẫn này sẽ được sử dụng làm
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
118 của hệ thống phân cấp tệp mà bạn sẽ tạo lạiCông việc thực tế xảy ra ở dòng 19 đến 23. Trước tiên, bạn tạo một đường dẫn duy nhất,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
119, đây sẽ là gốc của hệ thống phân cấp tệp mới của bạn. Sau đó, bạn lặp qua tất cả các đường dẫn bên dưới bản gốc >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
118 và tạo lại chúng dưới dạng các tệp trống bên trong hệ thống phân cấp tệp mớiĐể thao tác với các đường dẫn như thế này,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
121 trong thư viện tiêu chuẩn khá hữu ích. Để biết thêm chi tiết về cách nó được sử dụng, hãy xem Mô-đun >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
121 của Python 3. Thuần hóa hệ thống tập tinTrên dòng 26, bạn gọi
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
123. Bạn sẽ tìm hiểu thêm về bài kiểm tra >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
124 ở dòng 25 sau. Bây giờ, bạn nên biết rằng biến đặc biệt >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
125 có giá trị >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
126 bên trong các tập lệnh, nhưng nó lấy tên của mô-đun bên trong các mô-đun đã nhập. Để biết thêm thông tin về >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
125, hãy xem Xác định hàm chính trong Python và Điều gì sẽ xảy ra nếu tên == “chính” Làm trong Python?Lưu ý rằng bạn nhập
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
128 trên dòng 8. Mô-đun thư viện này chứa hai chức năng tiện ích>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
8>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
129 sử dụng bộ đếm để tìm đường dẫn chưa tồn tại. Trong ứng dụng, bạn sử dụng nó để tìm một thư mục con duy nhất để sử dụng làm >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
119 của hệ thống phân cấp tệp được tạo lại. Tiếp theo, >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
131 đảm bảo rằng tất cả các thư mục cần thiết đã được tạo trước khi tạo một tệp trống bằng cách sử dụng >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
132Hãy xem lại việc nhập
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
128>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
9Nó 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 độngMay 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', ...]
10Trong 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', ...]
11Tậ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àngVề 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', ...]
12Tại sao nó không hoạt động?
Vấn đề là khi khởi động ứng dụng bằng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
139, bạn đã thay đổi vị trí của tập lệnh hiện tại, do đó thay đổi đường dẫn nhập. >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
128 không còn trên đường dẫn nhập, vì vậy không thể nhập hoàn toànMột giải pháp khả thi là thay đổi đường dẫn nhập của Python
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
13Điều này hoạt động vì đường dẫn nhập bao gồm thư mục chứa
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
112 và >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
113. Vấn đề với phương pháp này là đường dẫn nhập của bạn có thể rất lộn xộn và khó hiểuTrên thực tế, bạn đang tạo lại một tính năng của các phiên bản Python đầu tiên được gọi là nhập tương đối ngầm định. Chúng đã bị xóa khỏi ngôn ngữ bởi PEP 328 với lý do sau
Trong Python 2. 4 trở về trước, nếu bạn đang đọc một mô-đun nằm bên trong một gói, thì không rõ liệu
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]>>> import math >>> dir[] ['__annotations__', '__builtins__', ..., 'math'] >>> dir[math] ['__doc__', ..., 'nan', 'pi', 'pow', ...]
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', ...]
14Giờ đâ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', ...]
15Thậ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', ...]
16Vấn đề là các lần nhập tương đối được giải quyết khác nhau trong các tập lệnh so với các mô-đun đã nhập. Tất nhiên, bạn có thể quay lại và khôi phục quá trình nhập tuyệt đối trước khi chạy tập lệnh trực tiếp hoặc thậm chí bạn có thể thực hiện một số động tác nhào lộn
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
153 để nhập tệp hoàn toàn hoặc tương đối tùy thuộc vào những gì hoạt độngThậ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 HettingerPhả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', ...]
155Remove adsTạo và cài đặt gói cục bộ
Khi bạn cài đặt một gói từ PyPI, gói đó có sẵn cho tất cả các tập lệnh trong môi trường của bạn. Tuy nhiên, bạn cũng có thể cài đặt các gói từ máy tính cục bộ của mình và chúng cũng sẽ được cung cấp theo cách tương tự
Tạo một gói cục bộ không liên quan đến nhiều chi phí. Đầu tiên, tạo các tệp
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
156 và >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
157 tối thiểu trong thư mục >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
114 bên ngoài>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
17Về 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ụngMộ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', ...]
18Lệnh này sẽ cài đặt gói vào hệ thống của bạn. Sau đó,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
114 sẽ được tìm thấy trên đường dẫn nhập của Python, nghĩa là bạn có thể sử dụng nó ở bất cứ đâu mà không phải lo lắng về thư mục tập lệnh, quá trình nhập tương đối hoặc các biến chứng khác. Tùy chọn >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
166 có nghĩa là có thể chỉnh sửa, tùy chọn này rất quan trọng vì tùy chọn này cho phép bạn thay đổi mã nguồn của gói mà không cần cài đặt lạiGhi chú. Loại tệp thiết lập này hoạt động rất tốt khi bạn tự làm việc với các dự án. Tuy nhiên, nếu bạn định chia sẻ mã với người khác thì bạn nên thêm một số thông tin khác vào tệp thiết lập của mình
Để biết thêm chi tiết về các tệp thiết lập, hãy xem Cách xuất bản Gói Python mã nguồn mở lên PyPI
Giờ đây,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
114 đã được cài đặt trên hệ thống của bạn, bạn có thể sử dụng câu lệnh nhập sau>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
19Điều này sẽ hoạt động bất kể bạn kết thúc cuộc gọi ứng dụng của mình như thế nào
Mẹo. Trong mã của riêng bạn, bạn nên tách biệt các tập lệnh và thư viện một cách có ý thức. Đây là một quy tắc tốt
- Một kịch bản có nghĩa là để được chạy
- Một thư viện có nghĩa là được nhập khẩu
Bạn có thể có mã mà bạn muốn tự chạy và nhập từ các tập lệnh khác. Trong trường hợp đó, thường đáng để cấu trúc lại mã của bạn để bạn chia phần chung thành một mô-đun thư viện
Mặc dù nên tách biệt các tập lệnh và thư viện, nhưng tất cả các tệp Python đều có thể được thực thi và nhập. Trong phần sau, bạn sẽ tìm hiểu thêm về cách tạo các mô-đun xử lý tốt cả hai
Gói không gian tên
Các mô-đun và gói Python có liên quan rất chặt chẽ với các tệp và thư mục. Điều này khiến Python khác biệt với nhiều ngôn ngữ lập trình khác, trong đó các gói chỉ hoạt động như các không gian tên mà không thực thi cách tổ chức mã nguồn. Xem các cuộc thảo luận trong PEP 402 để biết ví dụ
Các gói không gian tên đã có sẵn trong Python kể từ phiên bản 3. 3. Chúng ít phụ thuộc vào hệ thống phân cấp tệp cơ bản. Đặc biệt, các gói không gian tên có thể được chia thành nhiều thư mục. Gói không gian tên được tạo tự động nếu bạn có một thư mục chứa tệp
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
47 nhưng không có tệp >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
66. Xem PEP 420 để được giải thích chi tiếtGhi chú. Nói chính xác, các gói không gian tên ẩn đã được giới thiệu trong Python 3. 3. Trong các phiên bản trước của Python, bạn có thể tạo thủ công các gói không gian tên theo một số cách không tương thích khác nhau. PEP 420 thống nhất và đơn giản hóa các phương pháp trước đó
Để hiểu rõ hơn về lý do tại sao các gói không gian tên có thể hữu ích, hãy thử triển khai một. Như một ví dụ thúc đẩy, bạn sẽ có một cách khác để giải quyết vấn đề trong Mẫu phương thức xuất xưởng và triển khai của nó trong Python. được cung cấp một đối tượng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
170, bạn muốn chuyển đổi nó thành một trong số các biểu diễn chuỗi. Nói cách khác, bạn muốn tuần tự hóa các đối tượng >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
170Để cụ thể hơn, bạn muốn triển khai mã hoạt động giống như thế này
>>>
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
40Giả 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', ...]
41Tệ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', ...]
42Giao diện bộ nối tiếp này có một chút hạn chế, nhưng nó sẽ đủ để chứng minh cách các gói không gian tên hoạt động
Tệp
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
173 chứa một >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
174 tương tự có thể chuyển đổi một đối tượng thành XML>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
43Lư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', ...]
177Sau đó, 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', ...]
44Mộ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', ...]
45Bằ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ìnhGhi chú. Bạn có thể nhận được một
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
183 hoặc một >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
184 khi tự chạy mã. Điều này là do >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
181 không có trong đường dẫn nhập Python của bạn. Bạn sẽ sớm biết cách giải quyết vấn đề đóCàng xa càng tốt. Tuy nhiên, bây giờ bạn nhận ra rằng bạn cũng cần chuyển đổi các bài hát của mình sang biểu diễn YAML, không được hỗ trợ trong thư viện của bên thứ ba. Nhập sự kỳ diệu của các gói không gian tên. bạn có thể thêm
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
186 của riêng mình vào gói >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
181 mà không cần chạm vào thư viện của bên thứ baĐầu tiên, tạo một thư mục trên hệ thống tệp cục bộ của bạn có tên là
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
181. Điều quan trọng là tên của thư mục phải khớp với tên của gói không gian tên mà bạn đang tùy chỉnh>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
46Trong 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', ...]
47Vì 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', ...]
48Lư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', ...]
198Tiế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', ...]
49Cũ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ạnGhi 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', ...]
10Giờ đây, bạn có thể sử dụng tất cả các bộ nối tiếp mà không phải lo lắng về việc chúng được xác định trong gói của bên thứ ba hay cục bộ
Remove adsHướ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ư
408>>> import math >>> dir[] ['__annotations__', '__builtins__', ..., 'math'] >>> dir[math] ['__doc__', ..., 'nan', 'pi', 'pow', ...]
>>> 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', ...]
11Lưu ý cách nhóm này làm cho các phụ thuộc của mô-đun này rõ ràng.
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
411 và >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
412 cần được cài đặt trên hệ thống. Nói chung, bạn có thể cho rằng thư viện tiêu chuẩn có sẵn. Việc tách nhập khẩu từ bên trong gói của bạn cung cấp cho bạn một số tổng quan về các phụ thuộc nội bộ của mã của bạnCó những trường hợp nên bẻ cong các quy tắc này một chút. Bạn đã thấy rằng nhập tương đối có thể là một giải pháp thay thế cho việc tổ chức phân cấp gói. Sau này, bạn sẽ thấy trong một số trường hợp, bạn có thể di chuyển quá trình nhập vào định nghĩa hàm để phá vỡ các chu kỳ nhập như thế nào
Nhập tài nguyên
Đôi khi, bạn sẽ có mã phụ thuộc vào tệp dữ liệu hoặc các tài nguyên khác. Trong các tập lệnh nhỏ, đây không phải là vấn đề—bạn có thể chỉ định đường dẫn đến tệp dữ liệu của mình và tiếp tục
Tuy nhiên, nếu tệp tài nguyên quan trọng đối với gói của bạn và bạn muốn phân phối gói của mình cho những người dùng khác, thì một số thách thức sẽ phát sinh
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
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>>> import math >>> dir[] ['__annotations__', '__builtins__', ..., 'math'] >>> dir[math] ['__doc__', ..., 'nan', 'pi', 'pow', ...]
Gói của bạn có thể nằm trong tệp ZIP hoặc tệp
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>>> import math >>> dir[] ['__annotations__', '__builtins__', ..., 'math'] >>> dir[math] ['__doc__', ..., 'nan', 'pi', 'pow', ...]
Đã 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ênGiớ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', ...]
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417 cấp quyền truy cập vào tài nguyên trong các gói. Trong ngữ cảnh này, tài nguyên là bất kỳ tệp nào nằm trong gói có thể nhập. Tệp có thể tương ứng hoặc không tương ứng với tệp vật lý trên hệ thống tệpĐiều này có một vài lợi thế. Bằng cách sử dụng lại hệ thống nhập, bạn sẽ có cách xử lý nhất quán hơn với các tệp bên trong các gói của mình. Nó cũng cho phép bạn truy cập dễ dàng hơn vào các tệp tài nguyên trong các gói khác. Các tài liệu tổng hợp nó độc đáo
Nếu bạn có thể nhập một gói, bạn có thể truy cập các tài nguyên trong gói đó. [Nguồn]
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417 đã trở thành một phần của thư viện chuẩn trong Python 3. 7. Tuy nhiên, trên các phiên bản Python cũ hơn, một cổng sau có sẵn dưới dạng >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
421. Để sử dụng backport, hãy cài đặt nó từ PyPI>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
12Backport 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', ...]
66Ví 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ườngSau đó, bạn có thể sử dụng
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
426 và >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
427 để mở tệp văn bản và tệp nhị phân tương ứng>>>
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
14>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
426 và >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
427 tương đương với >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
430 tích hợp với tham số >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
431 được đặt lần lượt là >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
432 và >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
433. Các chức năng thuận tiện để đọc văn bản hoặc tệp nhị phân trực tiếp cũng có sẵn như >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
434 và >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
435. Xem tài liệu chính thức để biết thêm thông tinGhi 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', ...]
15Xem 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ế
Remove adsThí dụ. Sử dụng tệp dữ liệu
Là một ví dụ đầy đủ hơn về việc sử dụng tệp dữ liệu, bạn sẽ thấy cách triển khai chương trình đố vui dựa trên dữ liệu dân số của Liên hợp quốc. Đầu tiên, tạo gói
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
437 và tải xuống >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
438 từ trang web của Liên hợp quốc>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
16Mở tệp CSV và xem dữ liệu
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
17Mỗ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', ...]
18Cá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 PythonHà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', ...]
19Bạ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', ...]
30Các chi tiết của việc triển khai nằm quá xa chủ đề của hướng dẫn này, vì vậy chúng sẽ không được thảo luận ở đây. Tuy nhiên, bạn có thể mở rộng phần bên dưới để xem mã nguồn hoàn chỉnh
Mã nguồn của bài kiểm tra dân sốHiển thị/Ẩn
Bài kiểm tra dân số bao gồm hai chức năng, một chức năng đọc dữ liệu dân số như bạn đã làm ở trên và một chức năng chạy bài kiểm tra thực tế
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
31Lư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ệtVí 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 ứng dụ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 ảnhHãy nhớ rằng, khi phân phối gói của bạn, bạn thậm chí không đả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', ...]
33Nế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
Get the Source Code. Click here to get the source code you’ll use to learn about the Python import system in this tutorial
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 PyPIGUI đượ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', ...]
35Nế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 bị thu gom rác. Do cách tương tác của Python và Tk, 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
Remove adsNhậ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
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
463 để nó không làm gì cả>>>
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
36Về 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ịchGhi 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ẽ tìm hiểu 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
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
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', ...]
39Trong 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', ...]
472Thí 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ụ về serializers 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
30Nhà 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', ...]
180The factory makes some strong assumptions about the naming of both the module and the class containing the individual serializers. In the next section, you’ll learn about a plugin architecture that allows more flexibility
You can now re-create the earlier example as follows
>>>
>>> import math
>>> math.pi
3.141592653589793
31In this case, you no longer need to explicitly import each serializer. Instead, you specify the name of a serializer with a string. The string could even be chosen by your user at runtime
Note. In a regular package, you probably would have implemented
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
477 and >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
479 in an >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
66 file. That would have allowed you to simply import >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
181 and then call >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
485However, namespace packages aren’t allowed to use
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
66, so you need to implement these functions in a separate module insteadThe final example shows that you also get a decent error message if you try to serialize to a format that hasn’t been implemented
Remove adsExample. Một gói plugin
Let’s look at another example of using dynamic imports. You can use the following module to set up a flexible plugin architecture in your code. Đ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
One application that uses plugins effectively is the Glue exploratory visualization tool. Glue can read many different data formats out of the box. However, if your data format isn’t supported, then you can write your own custom data loader
You do this by adding a function that you decorate and place in a special location to make it easy for Glue to find. You don’t need to alter any part of the Glue source code. See the documentation for all the details
You can set up a similar plugin architecture that you can use in your own projects. Within the architecture, there are two levels
- A plugin package is a collection of related plugins corresponding to a Python package
- A plugin is a custom behavior made available in a Python module
The
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
487 module that exposes the plugin architecture has the following functions>>> import math
>>> math.pi
3.141592653589793
32The factory functions are used to conveniently add functionality to plugin packages. You’ll see some examples of how they’re used shortly
Looking at all the details of this code is outside the scope of this tutorial. If you’re interested, then you can see an implementation by expanding the section below
Complete Source Code of plugins. pyShow/Hide
The following code shows the implementation of
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
488 described above>>> import math
>>> math.pi
3.141592653589793
33This implementation is a bit simplified. In particular, it doesn’t do any explicit error handling. Check out the PyPlugs project for a more complete implementation
You can see that
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
489 uses >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
490 to dynamically load plugins. Additionally, >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
491 uses >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
492 to list all available plugins in a given packageLet’s look at some examples of how to use plugins. The first example is a
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
493 package that you can use to add many different greetings to your app. A full plugin architecture is definitely overkill for this example, but it shows how the plugins workAssume you have the following
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
493 package>>> import math
>>> math.pi
3.141592653589793
34Each
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
493 module defines a function that takes one >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
159 argument. Note how they’re all registered as plugins using the >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
497 decorator>>> import math
>>> math.pi
3.141592653589793
35To learn more about decorators and how they’re used, check out Primer on Python Decorators
Note. To simplify the discovery and import of plugins, each plugin’s name is based on the name of the module that contains it instead of the function name. This restricts you to having only one plugin per file
To finish setting up
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
493 as a plugin package, you can use the factory functions in >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
487 to add functionality to the >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
493 package itself>>> import math
>>> math.pi
3.141592653589793
36You can now use
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
101 and >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
102 as follows>>>
>>> import math
>>> math.pi
3.141592653589793
37Note that
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
101 automatically discovers all the plugins that are available in the packageYou can also more dynamically choose which plugin to call. In the following example, you choose a plugin at random. However, you could also select a plugin based on a configuration file or user input
>>>
>>> import math
>>> math.pi
3.141592653589793
38To discover and call the different plugins, you need to import them. Let’s have a quick look at how
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
487 handles imports. The main work is done in the following two functions inside >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
488>>> import math
>>> math.pi
3.141592653589793
39>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
489 looks deceptively straightforward. Nó sử dụng >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
469 để nhập một mô-đun. But there are a couple of things also happening in the background- Python’s import system ensures that each plugin is imported only once
497 decorators defined inside each plugin module register each imported plugin>>> import math >>> dir[] ['__annotations__', '__builtins__', ..., 'math'] >>> dir[math] ['__doc__', ..., 'nan', 'pi', 'pow', ...]
- In a full implementation, there would also be some error handling to deal with missing plugins
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
491 discovers all the plugins within a package. Here’s how it works
110 from>>> import math >>> dir[] ['__annotations__', '__builtins__', ..., 'math'] >>> dir[math] ['__doc__', ..., 'nan', 'pi', 'pow', ...]
417 lists all the files inside a package>>> import math >>> dir[] ['__annotations__', '__builtins__', ..., 'math'] >>> dir[math] ['__doc__', ..., 'nan', 'pi', 'pow', ...]
- The results are filtered to find potential plugins
- Each Python file not starting with an underscore is imported
- Plugins in any of the files are discovered and registered
Let’s end this section with a final version of the serializers namespace package. One outstanding issue was that the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
477 factory made strong assumptions about the naming of the serializer classes. You can make this more flexible using pluginsFirst, add a line registering each of the serializers. Here is an example of how it’s done in the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
197 serializer>>> import math
>>> math.pi
3.141592653589793
70Next, update
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
114 to use >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
487>>> import math
>>> math.pi
3.141592653589793
71You implement
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
477 using >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
117 since that will automatically instantiate each serializer. With this refactoring, the serializers work just the same as earlier. However, you have more flexibility in naming your serializer classesFor more information about using plugins, check out PyPlugs on PyPI and the Plug-ins. Adding Flexibility to Your Apps presentation from PyCon 2019
Remove adsThe Python Import System
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à
- Tìm kiếm
- Nạp vào
- 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ênFor instance, the following methods of importing and renaming
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
53 are roughly equivalent>>>
>>> import math
>>> math.pi
3.141592653589793
72Of course, in normal code you should prefer the former
One thing to note is that, even when you import only one attribute from a module, the whole module is loaded and executed. The rest of the contents of the module just aren’t bound to the current namespace. One way to prove this is to have a look at what’s known as the module cache
>>>
>>> import math
>>> math.pi
3.141592653589793
73>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
121 acts as a module cache. It contains references to all modules that have been importedThe module cache plays a very important role in the Python import system. The first place Python looks for modules when doing an import is in
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
121. If a module is already available, then it isn’t loaded againThis is a great optimization, but it’s also a necessity. 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
Recall the import path you saw earlier. It essentially tells Python where to search for modules. However, if Python finds a module in the module cache, then it won’t bother searching the import path for the module
Example. Singletons as Modules
In object-oriented programming, a singleton is a class with at most one instance. While it’s possible to implement singletons in Python, most good uses of singletons can be handled by modules instead. You can trust the module cache to instantiate a class only once
As an example, let’s return to the United Nations population data you saw earlier. The following module defines a class wrapping the population data
>>> import math
>>> math.pi
3.141592653589793
74Reading the data from disk takes some time. Since you don’t expect the data file to change, you instantiate the class when you load the module. The name of the class starts with an underscore to indicate to users that they shouldn’t use it
You can use the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
123 singleton to create a Matplotlib graph showing the population projection for the most populous countries>>>
>>> import math
>>> math.pi
3.141592653589793
75This creates a chart like the following
Note that loading the data at import time is a kind of antipattern. Ideally, you want your imports to be as free of side effects as possible. A better approach would be to load the data lazily when you need it. You can do this quite elegantly using properties. Expand the following section to see an example
Lazily Loading Population DataShow/Hide
The lazy implementation of
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
124 stores the population data in >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
125 the first time it’s read. The >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
126 property handles this caching of data>>> import math
>>> math.pi
3.141592653589793
76Now the data won’t be loaded at import time. Instead, it’ll be imported the first time you access the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
127 dictionary. For more information about properties and the more general concept of descriptors, see Python Descriptors. An IntroductionRemove adsReloading Modules
The module cache can be a little frustrating when you’re working in the interactive interpreter. It’s not trivial to reload a module after you change it. For example, take a look at the following module
>>> import math
>>> math.pi
3.141592653589793
77As part of testing and debugging this module, you import it in a Python console
>>>
>>> import math
>>> math.pi
3.141592653589793
78Let’s say you realize that you have a bug in your code, so you update the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
128 file in your editor>>> import math
>>> math.pi
3.141592653589793
79Returning to your console, you import the updated module to see the effect of your fix
>>>
>>> import math
>>> math.pi
3.141592653589793
78Why is the answer still
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
129? The module cache is doing its [now frustrating] magic. since Python imported >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
130 earlier, it sees no reason to load the module again even though you just changed itThe most straightforward solution to this is to exit the Python console and restart it. This forces Python to clear its module cache as well
>>>
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
01However, restarting the interpreter isn’t always feasible. You might be in a more complicated session that has taken you a long time to set up. If that’s the case, then you can use
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
131 to reload a module instead>>>
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
02Note that
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
132 requires a module object, not a string like >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
472 does. Also, be aware that >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
132 has some caveats. In particular, variables referring to objects within a module are not re-bound to new objects when that module is reloaded. Xem tài liệu để biết thêm chi tiếtFinders and Loaders
You saw earlier that creating modules with the same name as standard libraries can create problems. For example, if you have a file named
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
135 in Python’s import path, then you won’t be able to import >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 from the standard libraryThis isn’t always the case, though. Create a file named
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
137 with the following content>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
03Next, open a Python interpreter and import this new module
>>>
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
04Something weird happened. It doesn’t seem like Python imported your new
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
138 module. Instead, it imported the >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
138 module from the standard library. Why are the standard library modules behaving inconsistently? You can get a hint by inspecting the modules>>>
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
05You can see that
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 is imported from a file, whereas >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
138 is some kind of built-in module. It seems that built-in modules aren’t shadowed by local onesNote. The built-in modules are compiled into the Python interpreter. Typically, they’re foundational modules like
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
142, >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
143, and >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
138. Which modules are built in depends on your Python interpreter, but you can find their names in >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
145Let’s dig even deeper into Python’s import system. This will also show why built-in modules aren’t shadowed by local ones. There are several steps involved when importing a module
Python checks if the module is available in the module cache. If
121 contains the name of the module, then the module is already available, and the import process ends>>> import math >>> dir[] ['__annotations__', '__builtins__', ..., 'math'] >>> dir[math] ['__doc__', ..., 'nan', 'pi', 'pow', ...]
Python starts looking for the module using several finders. A finder will search for the module using a given strategy. The default finders can import built-in modules, frozen modules, and modules on the import path
Python loads the module using a loader. Which loader Python uses is determined by the finder that located the module and is specified in something called a module spec
You can extend the Python import system by implementing your own finder and, if necessary, your own loader. You’ll see a more useful example of a finder later. For now, you’ll learn how to do basic [and possibly silly] customizations of the import system
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
147 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', ...]
06First, note that this answers the question from earlier. built-in modules aren’t shadowed by local modules because the built-in finder is called before the import path finder, which finds local modules. 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ìnhTo quickly mess up your Python session, you can remove all finders
>>>
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
07Vì 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', ...]
121Sau đâ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', ...]
08Tấ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. There are three ways that >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
151 can terminate- By returning
153 if it doesn’t know how to find and load the module>>> import math >>> dir[] ['__annotations__', '__builtins__', ..., 'math'] >>> dir[math] ['__doc__', ..., 'nan', 'pi', 'pow', ...]
- By returning a module spec specifying how to load the module
- By raising a
183 to indicate that the module can’t be imported>>> import math >>> dir[] ['__annotations__', '__builtins__', ..., 'math'] >>> dir[math] ['__doc__', ..., 'nan', 'pi', 'pow', ...]
The
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
155 prints a message to the console and then explicitly returns >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
153 to indicate that other finders should figure out how to actually import the moduleNote. Since Python implicitly returns
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
153 from any function or method without an explicit >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
158, you can leave out line 9. However, in this case it’s good to include >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
159 to make it clear that >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
155 doesn’t find a moduleBằ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', ...]
09You can, for instance, see that importing
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
162 triggers the import of several other modules that >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
162 depends on. Note that the verbose option to the Python interpreter, >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
164, gives the same information and much, much moreFor another example, say that you’re on a quest to rid the world of regular expressions. [Now, why would you want such a thing? Regular expressions are great. ] You could implement the following finder that bans the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
165 regular expressions module>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
20Raising a
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
183 ensures that no finder later in the list of finders will be executed. This effectively stops you from using regular expressions in Python>>>
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
21Even though you’re importing only
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
162, that module is importing >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
165 behind the scenes, so an error is raisedExample. Automatically Install From PyPI
Because the Python import system is already quite powerful and useful, there are many more ways to mess it up than there are to extend it in a useful way. However, the following example can be useful in certain situations
The Python Package Index [PyPI] is your one-stop cheese shop for finding third-party modules and packages. It’s also the place from which
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
155 downloads packagesIn other Real Python tutorials, you may have seen instructions to use
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
170 to install the third-party modules and packages you need for following along with examples. Wouldn’t it be great to have Python automatically install missing modules for you?Warning. In most cases, it really wouldn’t be great to have Python install modules automatically. For instance, in most production settings you want to stay in control of your environment. Furthermore, the documentation cautions against using
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
155 this wayTo avoid messing up your Python installation, you should play with this code only in environments that you wouldn’t mind deleting or reinstalling
The following finder attempts to install modules using
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
155>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
22So 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. If the installation works, then the module spec will be created and returnedTry to use the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
176 library without installing it yourself>>>
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
23Normally,
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
177 would’ve raised a >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
183, but in this case >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
176 is installed and importedWhile the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
173 seemingly works, there are some challenges with this approach. One major problem is that the import name of a module doesn’t always correspond to its name on PyPI. For example, the Real Python feed reader is called >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
181 on PyPI, but the import name is simply >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
182Using
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
173 to import and install >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
182 ends up installing the wrong package>>>
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
24This could have disastrous consequences for your project
One situation in which automatic installations can be quite helpful is when you’re running Python in the cloud with more limited control over your environment, such as when you’re running Jupyter-style notebooks at Google Colaboratory. The Colab notebook environment is great for doing cooperative data exploration
A typical notebook comes with many data science packages installed, including NumPy, Pandas, and Matplotlib, and you can add new packages with
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
155. But you can also activate automatic installationSince
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
186 isn’t available locally on the Colab server, the code is copied into the first cell of the notebookExample. Import Data Files
The final example in this section is inspired by Aleksey Bilogur’s great blog post Import Almost Anything in Python. An Intro to Module Loaders and Finders. You’ve already seen how to use
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417 to import datafiles. Here, you’ll instead implement a custom loader that can import a CSV file directlyTrước đó, bạn đã làm việc với một tệp CSV khổng lồ chứa dữ liệu dân số. To make the custom loader example more manageable, consider the following smaller
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
188 file>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
25The 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', ...]
26The 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', ...]
27There’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 detailAs 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', ...]
188For 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', ...]
301The 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 moduleFor 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', ...]
28In 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 51You 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 underscoreBy 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 onceImport Tips and Tricks
Để hoàn thiện hướng dẫn này, bạn sẽ thấy một số mẹo về cách xử lý các tình huống nhất định thỉnh thoảng xảy ra. You’ll see how to deal with missing packages, cyclical imports, and even packages stored inside ZIP files
Handle Packages Across Python Versions
Sometimes you need to deal with packages that have different names depending on the Python version. You’ve already seen one example of this.
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417 has only been available since Python 3. 7. In earlier versions of Python, you need to install and use >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
421 insteadAs long as the different versions of the package are compatible, you can handle this by renaming the package with
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
312>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
15In the rest of the code, you can refer to
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
313 and not worry about whether you’re using >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417 or >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
421Normally, it’s easiest to use a
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
153 statement to figure out which version to use. Another option is to inspect the version of the Python interpreter. However, this may add some maintenance cost if you need to update the version numbersYou could rewrite the previous example as follows
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
00This would use
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417 on Python 3. 7 and newer while falling back to >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
421 on older versions of Python. 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ạyHandle Missing Packages. Sử dụng một thay thế
The following use case is closely related to the previous example. Assume there’s a compatible reimplementation of a package. Việc triển khai lại được tối ưu hóa tốt hơn, vì vậy bạn muốn sử dụng nó nếu có sẵn. However, the original package is more easily available and also delivers acceptable performance
One such example is
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
320, which is an optimized version of >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
321 from the standard library. Bạn có thể xử lý các tùy chọn này giống như cách bạn đã xử lý các tên gói khác nhau trước đó>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
01This 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 notAnother 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', ...]
02By 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 importedHandle 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 availableFor a concrete example, say that you’re using Colorama to add colored text in the console. Colorama chủ yếu bao gồm các hằng số chuỗi đặc biệt có thêm màu khi in
>>>
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
03Unfortunately, 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 timeIf 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. Các màu sau đây có sẵn>>>
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
04You 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', ...]
337Finally,
>>> 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', ...]
05Note 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', ...]
06This 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 stringIt’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 là một chuỗi rỗng cũng sẽ trả về chuỗi rỗng khi nó được gọi. This effectively gives us a reimplementation of Colorama, just without the colorsThe 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 wellMô-đun
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
349 được thiết kế để thay thế thả xuống cho Colorama, vì vậy bạn có thể cập nhật ví dụ đếm ngược bằng tìm kiếm và thay thế>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
08If you run this script on a system in which Colorama isn’t available, then it’ll still work, but it may not look as nice
With Colorama installed, you should see the same results as earlier
Nhập tập lệnh dưới dạng mô-đun
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', ...]
09As JSON is often read only by machines, many JSON files aren’t formatted in a readable fashion. In fact, it’s quite common for JSON files to consist of one very long line of text
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
354 is a script that uses the >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
196 library to format JSON in a more readable fashion>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
10Now the structure of the JSON file becomes much less complicated to grasp. You can use the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
356 option to sort keys alphabeticallyWhile 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 scriptLet’s test it out. Create the following file
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
11If 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', ...]
12However, 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', ...]
13This behavior is leveraged in the following pattern
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
14Hãy sử dụng điều này trong một ví dụ lớn hơn. Với nỗ lực giúp bạn luôn trẻ trung, tập lệnh sau sẽ thay thế bất kỳ độ tuổi “già” nào [
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
361 trở lên] bằng >>> 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', ...]
15Bạn có thể chạy tập lệnh này dưới dạng tập lệnh và nó sẽ tương tác làm cho độ tuổi bạn nhập trẻ hơn
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
16Bạn cũng có thể sử dụng mô-đun làm thư viện có thể nhập. Bài kiểm tra
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
124 ở dòng 12 đảm bảo rằng không có tác dụng phụ khi bạn nhập thư viện. Chỉ các chức năng >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
364 và >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
365 được xác định. Ví dụ, bạn có thể sử dụng thư viện này như sau>>>
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
17Nếu không có sự bảo vệ của thử nghiệm
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
124, quá trình nhập sẽ kích hoạt >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
367 tương tác và khiến cho việc sử dụng >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
368 làm thư viện trở nên rất khó khănChạy tập lệnh Python từ tệp ZIP
Một tính năng hơi khó hiểu của Python là nó có thể chạy các tập lệnh được đóng gói thành các tệp ZIP. Ưu điểm chính của điều này là bạn có thể phân phối một gói đầy đủ dưới dạng một tệp
Note, however, that this still requires Python to be installed on the system. Nếu bạn muốn phân phối ứng dụng Python của mình dưới dạng tệp thực thi độc lập, hãy xem Sử dụng PyInstaller để dễ dàng phân phối ứng dụng Python
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', ...]
18This will print a message when you run it
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
19Now 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', ...]
20On 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. Bây giờ bạn có thể gọi nó trực tiếp bằng Python>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
21Note 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 fileThink 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 neededThe app consists of the following files
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
22You 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', ...]
23This command essentially does two things. it creates an entry point and packages your application
Remember that you needed a
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
455 file as an entry point inside your ZIP archive. If you supply the >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
458 option with information about how your app should be started, then >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
375 creates this file for you. In this example, the generated >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
455 looks like this>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
24This
>>> 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 archiveNote. 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 optionHowever, 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 informationOn 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', ...]
25The
>>> 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', ...]
26Notice the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
394 in front of the filename. This is a typical trick on Mac and Linux to run executable files in the current directory. If you move the file to a directory on your >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
395, or if you’re using Windows, then you should be able to use only the filename. >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
382Note. On Python 3. 6 and older, the previous command will fail with a message saying that it couldn’t find the population data resource in the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
437 directory. This is due to a limitation in >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
398A workaround is to supply the absolute path to
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
382. On Mac and Linux, you can do this with the following trick>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
27The
>>> import math
>>> math.pi
3.141592653589793
300 command expands to the path of the current directoryLet’s close this section by looking at a nice effect of using
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417. Remember that you used the following code to open the data file>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
28A more common way to open data files is to locate them based on your module’s
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
413 attribute>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
29This approach usually works well. However, it falls apart when your application is packed into a ZIP file
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
30Your data file is inside the ZIP archive, so
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
430 isn’t able to open it. >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
417, on the other hand, will extract your data to a temporary file before opening itXử lý nhập khẩu theo chu kỳ
A cyclical import happens when you have two or more modules importing each other. More concretely, imagine that the module
>>> import math
>>> math.pi
3.141592653589793
305 uses >>> import math
>>> math.pi
3.141592653589793
306 and the module >>> import math
>>> math.pi
3.141592653589793
307 similarly imports >>> import math
>>> math.pi
3.141592653589793
305Python’s import system is to some extent designed to handle import cycles. For instance, the following code—while not very useful—runs fine
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
31Trying to import
>>> import math
>>> math.pi
3.141592653589793
305 in the interactive interpreter imports >>> import math
>>> math.pi
3.141592653589793
307 as well>>>
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
32Note that
>>> import math
>>> math.pi
3.141592653589793
307 is imported in the middle of the import of >>> import math
>>> math.pi
3.141592653589793
305, precisely at the >>> import math
>>> math.pi
3.141592653589793
306 statement in the source code of >>> import math
>>> math.pi
3.141592653589793
305. The reason this doesn’t end up in endless recursion is our old friend the module cacheWhen you type
>>> import math
>>> math.pi
3.141592653589793
315, a reference to >>> import math
>>> math.pi
3.141592653589793
305 is added to the module cache even before >>> import math
>>> math.pi
3.141592653589793
305 is loaded. When >>> import math
>>> math.pi
3.141592653589793
307 tries to import >>> import math
>>> math.pi
3.141592653589793
305 later, it simply uses the reference in the module cacheYou can also have modules that do something slightly more useful. If you define attributes and functions in your modules, then it all still works
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
33Importing
>>> import math
>>> math.pi
3.141592653589793
305 works the same as before>>>
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
32The issues associated with recursive imports start popping up when you actually use the other module at import time instead of just defining functions that will use the other module later. Add one line to
>>> import math
>>> math.pi
3.141592653589793
321>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
35Now Python gets confused by the import
>>>
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
36The error message may seem a bit puzzling at first. 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 moduleThe 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
328To 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', ...]
37By 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', ...]
38So 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. If you see cycles in your architecture sketches, have a closer look and try to break the cycles
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. do your imports locally inside functions
Note that in the following code,
>>> import math
>>> math.pi
3.141592653589793
306 is done inside >>> import math
>>> math.pi
3.141592653589793
328. This has two consequences. First, >>> import math
>>> math.pi
3.141592653589793
307 is available only inside the >>> import math
>>> math.pi
3.141592653589793
328 function. Quan trọng hơn, quá trình nhập không xảy ra cho đến khi bạn gọi >>> import math
>>> math.pi
3.141592653589793
328 sau khi >>> import math
>>> math.pi
3.141592653589793
305 đã được nhập đầy đủ>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
39Now there are no issues importing and using
>>> import math
>>> math.pi
3.141592653589793
305>>>
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
40Notice that
>>> import math
>>> math.pi
3.141592653589793
307 is, in fact, not imported until you call >>> import math
>>> math.pi
3.141592653589793
328. For another perspective on cyclical imports, see Fredrik Lundh’s classic noteProfile Imports
One concern when importing several modules and packages is that it will add to the startup time of your script. Depending on your application, this may or may not be critical
Kể từ khi phát hành Python 3. 7, you’ve had a quick way of knowing how much time it takes to import packages and modules. Python 3. 7 supports the
>>> import math
>>> math.pi
3.141592653589793
344 command-line option, which measures and prints how much time each module takes to import>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
41The
>>> import math
>>> math.pi
3.141592653589793
345 column shows the cumulative time of import [in microseconds] on a per-package basis. You can read the listing as follows. Python spent >>> import math
>>> math.pi
3.141592653589793
346 microseconds to fully import >>> import math
>>> math.pi
3.141592653589793
347, which involved importing >>> 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, and the C implementation >>> import math
>>> math.pi
3.141592653589793
350 as wellThe
>>> import math
>>> math.pi
3.141592653589793
351 column shows the time it took to import only the given module, excluding any recursive imports. You can see that >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
138 took >>> import math
>>> math.pi
3.141592653589793
353 microseconds to import, >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
49 took >>> import math
>>> math.pi
3.141592653589793
355, >>> import math
>>> math.pi
3.141592653589793
350 took >>> import math
>>> math.pi
3.141592653589793
357, and the import of >>> import math
>>> math.pi
3.141592653589793
347 itself took >>> import math
>>> math.pi
3.141592653589793
359 microseconds. All in all, this adds up to a cumulative time of >>> import math
>>> math.pi
3.141592653589793
346 microseconds [within rounding errors]Have a look at the
>>> import math
>>> math.pi
3.141592653589793
361 example from the Colorama section>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
42In this example, importing
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
349 took almost 0. 013 seconds. Most of that time was spent importing Colorama and its dependencies. The >>> import math
>>> math.pi
3.141592653589793
351 column shows the import time excluding nested importsFor an extreme example, consider the
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
124 singleton from earlier. Because it’s loading a big data file, it’s extremely slow to import. To test this, you can run >>> import math
>>> math.pi
3.141592653589793
365 as a script with the >>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
386 option>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
43In this case, it takes almost 2 seconds to import
>>> import math
>>> dir[]
['__annotations__', '__builtins__', ..., 'math']
>>> dir[math]
['__doc__', ..., 'nan', 'pi', 'pow', ...]
124, of which about 1. 6 seconds are spent in the module itself, mainly for loading the data file>>> import math
>>> math.pi
3.141592653589793
344 is a great tool for optimizing your imports. If you need to do more general monitoring and optimization of your code, then check out Python Timer Functions. Three Ways to Monitor Your CodeConclusion
In this tutorial, you’ve gotten to know the Python import system. Like many things in Python, it’s fairly straightforward to use for basic tasks like importing modules and packages. At the same time, the import system is quite complex, flexible, and extendable. You’ve learned several import-related tricks that you can take advantage of in your own code
In this tutorial, you’ve learned how to
- Create namespace packages
- Import resources and data files
- Decide what to import dynamically at runtime
- Extend Python’s import system
- Handle different versions of packages
Throughout the tutorial, you’ve seen many links to further info. The most authoritative source on the Python import system is the official documentation
- The import system
- The
469 package>>> import math >>> dir[] ['__annotations__', '__builtins__', ..., 'math'] >>> dir[math] ['__doc__', ..., 'nan', 'pi', 'pow', ...]
- PEP 420. Implicit namespace packages
- Importing modules
You can put your knowledge of Python imports to use by following along with the examples in this tutorial. Click the link below for access to the source code
Get the Source Code. Click here to get the source code you’ll use to learn about the Python import system in this tutorial
Mark as Completed
🐍 Python Tricks 💌
Get a short & sweet Python Trick delivered to your inbox every couple of days. No spam ever. Unsubscribe any time. Curated by the Real Python team
Gửi cho tôi thủ thuật Python »
About Geir Arne Hjelle
Geir Arne is an avid Pythonista and a member of the Real Python tutorial team
» More about Geir ArneEach tutorial at Real Python is created by a team of developers so that it meets our high quality standards. The team members who worked on this tutorial are
Aldren
Brad
Dan
Joanna
Jacob
Master Real-World Python Skills With Unlimited Access to Real Python
Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas
Level Up Your Python Skills »
Master Real-World Python Skills
With Unlimited Access to Real Python
Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas
Level Up Your Python Skills »
What Do You Think?
Rate this article
Tweet Share Share EmailWhat’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use? Leave a comment below and let us know
Commenting Tips. The most useful comments are those written with the goal of learning from or helping out other students. Get tips for asking good questions and get answers to common questions in our support portal