Giải pháp tìm kiếm từ python
In Python, you use the 44 keyword to make code in one module available in another. 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 maintainable Show
This tutorial will provide a thorough overview of Python’s 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
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', ...] 44Python 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 adsModulesThe Python. org glossary defines module as follows
In practice, a module usually corresponds to one 47 file containing Python codeThe true power of modules is that they can be imported and reused in other code. Consider the following example >>>
In the first line, 48, you import the code in the 49 module and make it available to use. In the second line, you access the 50 variable within the 49 module. 49 is part of Python’s standard library, which means that it’s always available to import when you’re running PythonNote that you write 53 and not just simply 50. In addition to being a module, 49 acts as a namespace that keeps all the attributes of the module together. Namespaces are useful for keeping your code readable and organized. In the words of Tim Peters
You can list the contents of a namespace with 56>>>
Using 56 without any argument shows what’s in the global namespace. To see the contents of the 49 namespace, you use 59You’ve already seen the most straightforward use of 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 50 variable from the 49 module>>> 1Note that this places 50 in the global namespace and not within a 49 namespaceYou can also rename modules and attributes as they’re imported >>> 4For more details about the syntax for importing modules, check out Python Modules and Packages – An Introduction PackagesYou can use a package to further organize your modules. The Python. org glossary defines package as follows
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 66 inside it. The 66 file contains the contents of the package when it’s treated as a module. It can be left emptyNote. Directories without an 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 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 70 in a few different languages. The package will consist of the following directories and files 1Each country file prints out a greeting, while the 66 files selectively import some of the subpackages and submodules. The exact contents of the files are as follows 3Note that 72 imports only 73 and not 74. Similarly, 75 doesn’t import anything, while 76 imports 77 and 78 but not 79. Each country module will print a greeting when it’s importedLet’s play with the 80 package at the interactive prompt to get a better understanding of how the subpackages and submodules behave>>> 3When 74 is imported, the 82 and 83 modules are imported as well. You can see this because the country modules print a greeting when they’re imported>>> 7The 75 file is empty. This means that importing the 85 package creates the namespace but has no other effect>>> 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 Chi tiết kỹ thuật. The module namespace is implemented as a Python dictionary and is available at the 86 attribute>>> 2Bạn hiếm khi cần tương tác trực tiếp với 86Tương tự, không gian tên toàn cục của Python cũng là một từ điển. Bạn có thể truy cập nó thông qua 88It’s fairly common to import subpackages and submodules in an 66 file to make them more readily available to your users. You can see one example of this in the popular 90 packageRemove adsAbsolute and Relative ImportsRecall the source code of 72 in the earlier example 0You’ve already seen 92 statements such as 93, but what does the dot ( 94) in 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 73. ”There’s an equivalent absolute import statement in which you explicitly name the current package 1In fact, all imports in 80 could have been done explicitly with similar absolute importsNhập tương đối phải ở dạng 92 và vị trí bạn đang nhập phải bắt đầu bằng dấu chấmThe 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 PathHow does Python find the modules and packages it imports? You’ll see more details about the mechanics of the Python import system later. For now, just know that Python looks for modules and packages in its import path. This is a list of locations that are searched for modules to import Note. When you type 99, Python will look for 100 a few different places before searching the import pathIn particular, it’ll look in a module cache to see if 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 102. Broadly speaking, this list will contain three different kinds of locations
Typically, Python will start at the beginning of the list of locations and look for a given module in each location until the first match. Since the script directory or the current directory is always first in this list, you can make sure that your scripts find your self-made modules and packages by organizing your directories and being careful about which directory you run Python from However, you should also be careful that you don’t create modules that shadow, or hide, other important modules. As an example, say that you define the following 49 module 2Using this module works as expected >>> 3But this module also shadows the 49 module that’s included in the standard library. Unfortunately, that means our earlier example of looking up the value of π no longer works>>> 4The problem is that Python now searches your new 49 module for 50 instead of searching the 49 module in the standard libraryTo avoid these kinds of issues, you should be careful with the names of your modules and packages. In particular, your top-level module and package names should be unique. If 49 is defined as a submodule within a package, then it won’t shadow the built-in moduleRemove adsExample. Structure Your ImportsWhile it’s possible to organize your imports by using the current directory as well as by manipulating 103 and even 102, the process is often unruly and prone to errors. To see a typical example, consider the following application 5The app will re-create a given file structure by creating directories and empty files. The 112 file contains the main script, and 113 is a library module with a few functions for dealing with files. The following is an example of output from the app, in this case by running it in the 114 directory 6The two source code files as well as the automatically created 115 file are re-created inside a new directory named 116Now take a look at the source code. The main functionality of the app is defined in 112 7In lines 12 to 16, you read a root path from the command line. In the above example you use a dot, which means the current directory. This path will be used as the 118 of the file hierarchy that you’ll re-createThe actual work happens in lines 19 to 23. First, you create a unique path, 119, that will be the root of your new file hierarchy. Then you loop through all paths below the original 118 and re-create them as empty files inside the new file hierarchyFor manipulating paths like this, 121 in the standard library is quite useful. For more details on how it’s used, check out Python 3’s 121 Module. Thuần hóa hệ thống tập tinOn line 26, you call 123. You’ll learn more about the 124 test on line 25 later. For now, you should know that the special variable 125 has the value 126 inside scripts, but it gets the name of the module inside imported modules. For more information on 125, check out Defining Main Functions in Python and What Does if name == “main” Do in Python?Note that you import 128 on line 8. This library module contains two utility functions 8 129 uses a counter to find a path that doesn’t already exist. In the app, you use it to find a unique subdirectory to use as the 119 of the re-created file hierarchy. Next, 131 makes sure all necessary directories are created before creating an empty file using 132Have a look at the import of 128 again 9It looks quite innocent. However, as the project grows, this line will cause you some headaches. Even though you import 128 from the 114 project, the import is absolute. it doesn’t start with a dot. This means that 128 must be found in the import path for the import to workLuckily, the directory containing the current script is always in Python’s import path, so this works fine for now. However, if your project gains some traction, then it may be used in other ways For example, someone might want to import the script into a Jupyter Notebook and run it from there. Or they may want to reuse the 128 library in another project. They may even create an executable with PyInstaller to more easily distribute it. Unfortunately, any of these scenarios can create issues with the import of 128To see an example, you can follow the PyInstaller guide and create an entry point to your application. Add an extra directory outside your application directory 10In the outer directory, create the entry point script, 139 11This script will import 123 from your original script and run it. Note that 123 isn’t run when 114 is imported because of the 124 test on line 25 in 112. Điều đó có nghĩa là bạn cần chạy 123 một cách rõ ràngIn theory, this should work similarly to running the app directly 12Tại sao nó không hoạt động? Vấn đề là khi khởi động ứng dụng bằng 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. 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 13Điều này hoạt động vì đường dẫn nhập bao gồm thư mục chứa 112 và 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
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 112 như sau 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 15Thật không may, bạn không còn có thể gọi ứng dụng trực tiếp 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 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 102 trong hầu hết các trường hợp. Trích lời Raymond Hettinger
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 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 156 và 157 tối thiểu trong thư mục 114 bên ngoài 17Về lý thuyết, 159 và 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 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ư 162 hoặc tên người dùng của bạn. 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 155 18Lệnh này sẽ cài đặt gói vào hệ thống của bạn. Sau đó, 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 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, 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 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
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ênCá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 47 nhưng không có tệp 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 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 170Để cụ thể hơn, bạn muốn triển khai mã hoạt động giống như thế này >>> 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 41Tệp 172 chứa mã có thể tuần tự hóa một đối tượng thành định dạng JSON 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 173 chứa một 174 tương tự có thể chuyển đổi một đối tượng thành XML 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 175, 176 và 177Sau đó, bạn tạo một lớp 170 có thể sử dụng các bộ nối tiếp này 44Một 170 được xác định bởi ID, tiêu đề và nghệ sĩ của nó. Lưu ý rằng 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 181 của bên thứ ba, bạn có thể sử dụng nó như sau>>> 45Bằng cách cung cấp các đối tượng nối tiếp khác nhau cho 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 183 hoặc một 184 khi tự chạy mã. Điều này là do 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 186 của riêng mình vào gói 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à 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 46Trong tệp 189, bạn xác định 186 của riêng mình. Bạn căn cứ vào gói 191, gói này phải được cài đặt từ PyPI 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 192 48Lưu ý rằng 186 dựa trên 192, được nhập từ chính 181. Vì cả 196 và 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. 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 >>> 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 181. Trong mã thực tế, bạn sẽ sử dụng 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 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 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 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 402 cục bộ giống như bạn đã làm trong ví dụ 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 402 và 407 trong cùng một thư mục, sau đó tùy chỉnh đường dẫn Python của bạn như sau>>> 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ẩuPEP 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
409 and 410 are great tools for enforcing a consistent style on your importsHere’s an example of an import section inside the Real Python feed reader package 11Note how this grouping makes the dependencies of this module clear. 411 and 412 need to be installed on the system. You can generally assume that the standard library is available. Separating imports from within your package gives you some overview over the internal dependencies of your codeThere are cases in which it makes sense to bend these rules a little. You’ve already seen that relative imports can be an alternative to organizing package hierarchies. Later, you’ll see how in some cases you can move imports into a function definition to break import cycles Resource ImportsSometimes you’ll have code that depends on data files or other resources. In small scripts, this isn’t a problem—you can specify the path to your data file and carry on 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
Đã có một số nỗ lực giải quyết những thách thức này, bao gồm cả 416. Tuy nhiên, với việc đưa 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 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
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 421. Để sử dụng backport, hãy cài đặt nó từ PyPI 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 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 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 13 66 chỉ là một tệp trống cần thiết để chỉ định 425 như một gói thông thườngSau đó, bạn có thể sử dụng 426 và 427 để mở tệp văn bản và tệp nhị phân tương ứng>>> 14 426 và 427 tương đương với 430 tích hợp với tham số 431 được đặt lần lượt là 432 và 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ư 434 và 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 417 như sau 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ệuLà 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 437 và tải xuống 438 từ trang web của Liên hợp quốc 16Mở tệp CSV và xem dữ liệu 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 439 và 440 nhất định 18Các dòng được đánh dấu cho biết cách sử dụng 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 >>> 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 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ế 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ó 442 trong số 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ư 446, 447, v.v.Thí dụ. Thêm biểu tượng vào GUI TkinterKhi 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 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 449. Để tạo một 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. 417 giải quyết vấn đề này bằng cách cung cấp 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 452 làm trình quản lý ngữ cảnh bằng từ khóa 454>>> 32Đối với ví dụ đầy đủ, giả sử bạn có hệ thống phân cấp tệp sau 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 455. Tên này chỉ ra rằng tệp là điểm vào cho gói. Có tệp 455 cho phép gói của bạn được thực thi với 457 34Để biết thêm thông tin về cách gọi gói bằng 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à 459. Lưu ý rằng bạn sử dụng 417 để lấy đường dẫn của tệp hình ảnh 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 Python và Tk tương tác, trình thu gom rác trong Python (ít nhất là trong CPython) không đăng ký rằng hình ảnh được sử dụng bởi 461 và 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 độngMộ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 463 để nó không làm gì cả>>> 36Về mặt kỹ thuật, bạn không định nghĩa lại 463. Thay vào đó, bạn đang xác định một 463 khác che khuất cái tích hợp sẵn. Để quay lại sử dụng 463 ban đầu, bạn có thể xóa tùy chỉnh của mình bằng 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 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>>> 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', ...] 469Cho đến giờ, bạn đã sử dụng từ khóa 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 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ó 38 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 39Trong mỗi trường hợp, mô-đun được nhập động bởi 472Thí dụ. Phương thức xuất xưởng với các gói không gian tênNghĩ lại ví dụ về serializers trước đó. Với 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 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 181 cục bộ của bạn 30Nhà máy 477 có thể tự động tạo bộ nối tiếp dựa trên tham số 478 và sau đó, 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 180Nhà máy đưa ra một số giả định mạnh mẽ về cách đặt tên của cả mô-đun và lớp chứa các bộ nối tiếp riêng lẻ. Trong phần tiếp theo, bạn sẽ tìm hiểu về kiến trúc plugin cho phép linh hoạt hơn Bây giờ bạn có thể tạo lại ví dụ trước đó như sau >>> 31Trong trường hợp này, bạn không cần phải nhập rõ ràng từng bộ nối tiếp nữa. Thay vào đó, bạn chỉ định tên của bộ nối tiếp bằng một chuỗi. Chuỗi thậm chí có thể được chọn bởi người dùng của bạn khi chạy Ghi chú. Trong một gói thông thường, bạn có thể đã triển khai 477 và 479 trong tệp 66. Điều đó sẽ cho phép bạn chỉ cần nhập 181 và sau đó gọi 485Tuy nhiên, các gói không gian tên không được phép sử dụng 66, vì vậy bạn cần triển khai các chức năng này trong một mô-đun riêng thay thếVí dụ cuối cùng cho thấy rằng bạn cũng nhận được một thông báo lỗi phù hợp nếu bạn cố gắng tuần tự hóa thành một định dạng chưa được triển khai Remove adsThí dụ. Một gói pluginHãy xem một ví dụ khác về việc sử dụng nhập động. Bạn có thể sử dụng mô-đun sau để thiết lập kiến trúc plugin linh hoạt trong mã của mình. Điều này tương tự như ví dụ trước, trong đó bạn có thể cắm các bộ nối tiếp cho các định dạng khác nhau bằng cách thêm các mô-đun mới Một ứng dụng sử dụng plugin hiệu quả là công cụ trực quan hóa khám phá Keo. Keo có thể đọc được nhiều định dạng dữ liệu khác nhau. Tuy nhiên, nếu định dạng dữ liệu của bạn không được hỗ trợ thì bạn có thể viết trình tải dữ liệu tùy chỉnh của riêng mình Bạn làm điều này bằng cách thêm một chức năng mà bạn trang trí và đặt ở một vị trí đặc biệt để Keo dễ dàng tìm thấy. Bạn không cần thay đổi bất kỳ phần nào của mã nguồn Keo. Xem tài liệu để biết tất cả các chi tiết Bạn có thể thiết lập kiến trúc plugin tương tự mà bạn có thể sử dụng trong các dự án của riêng mình. Trong kiến trúc, có hai cấp độ
Mô-đun 487 hiển thị kiến trúc plugin có các chức năng sau 32Các chức năng của nhà máy được sử dụng để thêm chức năng vào các gói plugin một cách thuận tiện. Bạn sẽ thấy một số ví dụ về cách chúng được sử dụng trong thời gian ngắn Xem xét tất cả các chi tiết của mã này nằm ngoài phạm vi của hướng dẫn này. Nếu quan tâm, bạn có thể xem cách triển khai bằng cách mở rộng phần bên dưới Mã nguồn hoàn chỉnh của plugin. pyHiện/Ẩn Đoạn mã sau cho thấy việc triển khai 488 được mô tả ở trên 33Việc triển khai này được đơn giản hóa một chút. Đặc biệt, nó không thực hiện bất kỳ xử lý lỗi rõ ràng nào. Kiểm tra dự án PyPlugs để triển khai đầy đủ hơn Bạn có thể thấy rằng 489 sử dụng 490 để tải động các plugin. Ngoài ra, 491 sử dụng 492 để liệt kê tất cả các plugin có sẵn trong một gói nhất địnhHãy xem xét một số ví dụ về cách sử dụng plugin. Ví dụ đầu tiên là gói 493 mà bạn có thể sử dụng để thêm nhiều lời chào khác nhau vào ứng dụng của mình. Kiến trúc plugin đầy đủ chắc chắn là quá mức cần thiết cho ví dụ này, nhưng nó cho thấy cách thức hoạt động của các pluginGiả sử bạn có gói 493 sau 34Mỗi mô-đun 493 xác định một hàm nhận một đối số 159. Lưu ý cách tất cả chúng được đăng ký làm plugin bằng trình trang trí 497 35Để tìm hiểu thêm về các công cụ trang trí và cách chúng được sử dụng, hãy xem Primer on Python Decorators Ghi chú. Để đơn giản hóa việc khám phá và nhập plugin, tên của mỗi plugin dựa trên tên của mô-đun chứa nó thay vì tên chức năng. Điều này hạn chế bạn chỉ có một plugin cho mỗi tệp Để hoàn tất việc thiết lập 493 dưới dạng gói plugin, bạn có thể sử dụng các chức năng ban đầu trong 487 để thêm chức năng cho chính gói 493 36Bây giờ bạn có thể sử dụng 101 và 102 như sau>>> 37Lưu ý rằng 101 tự động phát hiện tất cả các plugin có sẵn trong góiBạn cũng có thể linh hoạt hơn trong việc chọn plugin để gọi. Trong ví dụ sau, bạn chọn ngẫu nhiên plugin. Tuy nhiên, bạn cũng có thể chọn plugin dựa trên tệp cấu hình hoặc đầu vào của người dùng >>> 38Để khám phá và gọi các plugin khác nhau, bạn cần nhập chúng. Hãy xem nhanh cách 487 xử lý việc nhập. Công việc chính được thực hiện ở hai chức năng sau bên trong 488 39 489 trông có vẻ đơn giản. Nó sử dụng 469 để nhập một mô-đun. Nhưng có một vài điều cũng xảy ra trong nền
491 khám phá tất cả các plugin trong một gói. Đây là cách nó hoạt động
Hãy kết thúc phần này với phiên bản cuối cùng của gói không gian tên serializers. Một vấn đề nổi bật là nhà máy 477 đã đưa ra các giả định mạnh mẽ về việc đặt tên cho các lớp bộ nối tiếp. Bạn có thể làm cho điều này linh hoạt hơn bằng cách sử dụng pluginĐầu tiên, thêm một dòng đăng ký từng bộ nối tiếp. Đây là một ví dụ về cách nó được thực hiện trong bộ nối tiếp 197 70Tiếp theo, cập nhật 114 để sử dụng 487 71Bạn triển khai 477 bằng cách sử dụng 117 vì điều đó sẽ tự động khởi tạo từng bộ nối tiếp. Với việc tái cấu trúc này, các bộ tuần tự hóa hoạt động giống như trước đó. Tuy nhiên, bạn có thể linh hoạt hơn trong việc đặt tên cho các lớp serializer của mìnhĐể biết thêm thông tin về cách sử dụng plugin, hãy xem PyPlugs trên PyPI và các Trình cắm. Thêm tính linh hoạt vào bản trình bày Ứng dụng của bạn từ PyCon 2019 Remove adsHệ thống nhập PythonBạn đã thấy nhiều cách để tận dụng hệ thống nhập của Python. 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à
Đố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 44—cả ba bước diễn ra tự động. Tuy nhiên, khi bạn sử dụng 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ênChẳng hạn, các phương pháp nhập và đổi tên 53 sau đây gần như tương đương>>> 72Tất nhiên, trong mã bình thường, bạn nên chọn cái trước Một điều cần lưu ý là, ngay cả khi bạn chỉ nhập một thuộc tính từ mô-đun, toàn bộ mô-đun sẽ được tải và thực thi. Phần còn lại của nội dung mô-đun không bị ràng buộc với không gian tên hiện tại. Một cách để chứng minh điều này là xem cái được gọi là bộ đệm mô-đun >>> 73 121 hoạt động như một bộ đệm mô-đun. Nó chứa các tham chiếu đến tất cả các mô-đun đã được nhậpBộ đệm mô-đun đóng một vai trò rất quan trọng trong hệ thống nhập Python. Nơi đầu tiên Python tìm kiếm các mô-đun khi thực hiện nhập là trong 121. Nếu một mô-đun đã có sẵn, thì nó sẽ không được tải lạiĐây là một tối ưu hóa tuyệt vời, nhưng nó cũng là một điều cần thiết. Nếu các mô-đun được tải lại mỗi khi chúng được nhập, thì bạn có thể gặp phải tình trạng không nhất quán trong một số trường hợp nhất định, chẳng hạn như khi mã nguồn cơ bản thay đổi trong khi tập lệnh đang chạy Nhớ lại đường dẫn nhập mà bạn đã thấy trước đó. Về cơ bản, nó cho Python biết nơi tìm kiếm các mô-đun. Tuy nhiên, nếu Python tìm thấy một mô-đun trong bộ đệm mô-đun, thì nó sẽ không bận tâm tìm kiếm đường dẫn nhập cho mô-đun Thí dụ. Singletons như các mô-đunTrong lập trình hướng đối tượng, một singleton là một lớp có nhiều nhất một thể hiện. Mặc dù có thể triển khai các singleton trong Python, nhưng thay vào đó, hầu hết các cách sử dụng tốt các singleton có thể được xử lý bởi các mô-đun. Bạn có thể tin tưởng bộ đệm mô-đun để khởi tạo một lớp chỉ một lần Ví dụ: hãy quay lại dữ liệu dân số của Liên hợp quốc mà bạn đã xem trước đó. Mô-đun sau định nghĩa một lớp bao bọc dữ liệu dân số 74Đọc dữ liệu từ đĩa mất một thời gian. Vì bạn không muốn tệp dữ liệu thay đổi, nên bạn khởi tạo lớp khi bạn tải mô-đun. Tên của lớp bắt đầu bằng dấu gạch dưới để cho người dùng biết rằng họ không nên sử dụng nó Bạn có thể sử dụng đơn lẻ 123 để tạo biểu đồ Matplotlib hiển thị dự báo dân số cho các quốc gia đông dân nhất>>> 75Điều này tạo ra một biểu đồ như sau Lưu ý rằng việc tải dữ liệu tại thời điểm nhập là một loại phản mẫu. Lý tưởng nhất là bạn muốn hàng nhập khẩu của mình không có tác dụng phụ nhất có thể. Cách tiếp cận tốt hơn là tải dữ liệu một cách lười biếng khi bạn cần. Bạn có thể làm điều này khá tao nhã bằng cách sử dụng các thuộc tính. Mở rộng phần sau để xem ví dụ Tải dữ liệu dân số một cách lười biếngHiển thị/Ẩn Việc triển khai lười biếng của 124 lưu trữ dữ liệu dân số trong 125 lần đầu tiên nó được đọc. Thuộc tính 126 xử lý bộ đệm dữ liệu này 76Bây giờ dữ liệu sẽ không được tải khi nhập. Thay vào đó, nó sẽ được nhập vào lần đầu tiên bạn truy cập từ điển 127. Để biết thêm thông tin về các thuộc tính và khái niệm tổng quát hơn về bộ mô tả, hãy xem Bộ mô tả Python. Một lời giới thiệuRemove adsTải lại mô-đunBộ đệm mô-đun có thể hơi khó chịu khi bạn đang làm việc trong trình thông dịch tương tác. Tải lại một mô-đun sau khi bạn thay đổi nó không phải là chuyện nhỏ. Ví dụ: hãy xem mô-đun sau 77Là một phần của quá trình thử nghiệm và gỡ lỗi mô-đun này, bạn nhập nó vào bảng điều khiển Python >>> 78Giả sử bạn nhận ra rằng bạn có một lỗi trong mã của mình, vì vậy bạn cập nhật tệp 128 trong trình chỉnh sửa của mình 79Quay trở lại bảng điều khiển của bạn, bạn nhập mô-đun đã cập nhật để xem hiệu quả của bản sửa lỗi của bạn >>> 78Tại sao câu trả lời vẫn là 129? . vì Python đã nhập 130 trước đó, nên không có lý do gì để tải lại mô-đun mặc dù bạn vừa thay đổi nóGiải pháp đơn giản nhất cho vấn đề này là thoát khỏi bảng điều khiển Python và khởi động lại nó. Điều này buộc Python cũng phải xóa bộ đệm mô-đun của nó >>> 01Tuy nhiên, khởi động lại trình thông dịch không phải lúc nào cũng khả thi. Bạn có thể đang ở trong một phiên phức tạp hơn khiến bạn mất nhiều thời gian để thiết lập. Nếu đúng như vậy, bạn có thể sử dụng 131 để tải lại một mô-đun thay thế>>> 02Lưu ý rằng 132 yêu cầu đối tượng mô-đun, không phải chuỗi như 472. Ngoài ra, hãy lưu ý rằng 132 có một số lưu ý. Cụ thể, các biến tham chiếu đến các đối tượng trong một mô-đun không bị ràng buộc lại với các đối tượng mới khi mô-đun đó được tải lại. Xem tài liệu để biết thêm chi tiếtTrình tìm và Trình tảiBạn đã thấy trước đó rằng việc tạo các mô-đun có cùng tên với các thư viện tiêu chuẩn có thể gây ra sự cố. Ví dụ: nếu bạn có một tệp có tên 135 trong đường dẫn nhập của Python, thì bạn sẽ không thể nhập 49 từ thư viện chuẩnĐiều này không phải luôn luôn như vậy, mặc dù. Tạo một tệp có tên 137 với nội dung sau 03Tiếp theo, mở trình thông dịch Python và nhập mô-đun mới này >>> 04Một cái gì đó kỳ lạ đã xảy ra. Có vẻ như Python không nhập mô-đun 138 mới của bạn. Thay vào đó, nó đã nhập mô-đun 138 từ thư viện chuẩn. Tại sao các mô-đun thư viện tiêu chuẩn hoạt động không nhất quán? >>> 05Bạn có thể thấy rằng 49 được nhập từ một tệp, trong khi 138 là một loại mô-đun tích hợp sẵn nào đó. Có vẻ như các mô-đun tích hợp không bị che khuất bởi các mô-đun cục bộGhi chú. Các mô-đun tích hợp được biên dịch thành trình thông dịch Python. Thông thường, chúng là các mô-đun nền tảng như 142, 143 và 138. Những mô-đun nào được tích hợp tùy thuộc vào trình thông dịch Python của bạn, nhưng bạn có thể tìm thấy tên của chúng trong 145Hãy tìm hiểu sâu hơn về hệ thống nhập của Python. Điều này cũng sẽ cho thấy lý do tại sao các mô-đun tích hợp không bị che khuất bởi các mô-đun cục bộ. Có một số bước liên quan khi nhập một mô-đun
Bạn có thể mở rộng hệ thống nhập Python bằng cách triển khai công cụ tìm của riêng bạn và, nếu cần, trình tải của riêng bạn. Bạn sẽ thấy một ví dụ hữu ích hơn về công cụ tìm sau. Hiện tại, bạn sẽ học cách thực hiện các tùy chỉnh cơ bản (và có thể ngớ ngẩn) của hệ thống nhập 147 kiểm soát công cụ tìm nào được gọi trong quá trình nhập>>> 06Đầu tiên, lưu ý rằng điều này trả lời câu hỏi từ trước đó. các mô-đun tích hợp không bị che khuất bởi các mô-đun cục bộ vì công cụ tìm tích hợp được gọi trước công cụ tìm đường dẫn nhập, tìm các mô-đun cục bộ. Thứ hai, lưu ý rằng bạn có thể tùy chỉnh 147 theo ý thích của mìnhĐể nhanh chóng làm rối phiên Python của bạn, bạn có thể xóa tất cả các công cụ tìm >>> 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, 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, 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 08Tất cả các công cụ tìm phải triển khai một phương thức lớp 151, phương thức này sẽ cố gắng tìm một mô-đun nhất định. Có ba cách mà 151 có thể chấm dứt
155 in một thông báo tới bảng điều khiển và sau đó trả về một cách rõ ràng 153 để chỉ ra rằng những người tìm kiếm khác nên tìm ra cách thực sự nhập mô-đunGhi chú. Vì Python hoàn toàn trả về 153 từ bất kỳ hàm hoặc phương thức nào mà không có 158 rõ ràng, bạn có thể bỏ qua dòng 9. Tuy nhiên, trong trường hợp này, tốt nhất là thêm vào 159 để làm rõ rằng 155 không tìm thấy mô-đunBằng cách chèn 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>>> 09Ví dụ: bạn có thể thấy rằng việc nhập 162 sẽ kích hoạt việc nhập một số mô-đun khác mà 162 phụ thuộc vào. Lưu ý rằng tùy chọn dài dòng cho trình thông dịch Python, 164, cung cấp thông tin tương tự và nhiều, nhiều hơn nữaVí dụ khác, giả sử bạn đang thực hiện nhiệm vụ loại bỏ thế giới của các biểu thức thông thường. (Bây giờ, tại sao bạn lại muốn một thứ như vậy? Cụm từ thông dụng thật tuyệt. ) Bạn có thể triển khai công cụ tìm sau cấm mô-đun biểu thức chính quy 165 20Nâng cao một 183 đảm bảo rằng không có công cụ tìm nào sau này trong danh sách công cụ tìm sẽ được thực thi. Điều này thực sự ngăn bạn sử dụng các biểu thức thông thường trong Python>>> 21Mặc dù bạn chỉ đang nhập 162, nhưng mô-đun đó đang nhập 165 ở hậu trường, do đó sẽ xảy ra lỗiThí dụ. Tự động cài đặt từ PyPIVì hệ thống nhập của Python đã khá mạnh mẽ và hữu ích, nên có nhiều cách để làm rối tung nó hơn là mở rộng nó theo cách hữu ích. Tuy nhiên, ví dụ sau có thể hữu ích trong một số trường hợp Chỉ mục gói Python (PyPI) là cửa hàng pho mát duy nhất của bạn để tìm các gói và mô-đun của bên thứ ba. Đây cũng là nơi mà các gói tải xuống của 155Trong các hướng dẫn Real Python khác, bạn có thể đã xem hướng dẫn sử dụng 170 để cài đặt các mô-đun và gói của bên thứ ba mà bạn cần để làm theo cùng với các ví dụ. Sẽ thật tuyệt nếu Python tự động cài đặt các mô-đun còn thiếu cho bạn phải không?Cảnh báo. Trong hầu hết các trường hợp, sẽ không tuyệt lắm nếu Python tự động cài đặt các mô-đun. Chẳng hạn, trong hầu hết các cài đặt sản xuất, bạn muốn kiểm soát môi trường của mình. Hơn nữa, tài liệu cảnh báo không nên sử dụng 155 theo cách nàyĐể tránh làm rối cài đặt Python của bạn, bạn chỉ nên sử dụng mã này trong các môi trường mà bạn không ngại xóa hoặc cài đặt lại Công cụ tìm sau cố gắng cài đặt các mô-đun bằng cách sử dụng 155 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. Bằng cách đặt công cụ tìm này cuối cùng trong danh sách công cụ tìm, bạn biết rằng nếu bạn gọi 173, thì mô-đun đó sẽ không được tìm thấy trên hệ thống của bạn. Do đó, công việc của 151 chỉ là thực hiện 175. Nếu quá trình cài đặt hoạt động, thì thông số mô-đun sẽ được tạo và trả vềCố gắng sử dụng thư viện 176 mà không cần tự cài đặt>>> 23Thông thường, 177 sẽ tăng một 183, nhưng trong trường hợp này, 176 được cài đặt và nhậpTrong khi 173 dường như hoạt động, có một số thách thức với cách tiếp cận này. Một vấn đề lớn là tên nhập của một mô-đun không phải lúc nào cũng tương ứng với tên của nó trên PyPI. Ví dụ: trình đọc nguồn cấp Python thực có tên là 181 trên PyPI, nhưng tên nhập chỉ đơn giản là 182Sử dụng 173 để nhập và cài đặt 182 kết thúc bằng việc cài đặt sai gói>>> 24Điều này có thể gây hậu quả tai hại cho dự án của bạn Một tình huống trong đó cài đặt tự động có thể khá hữu ích là khi bạn đang chạy Python trên đám mây với quyền kiểm soát hạn chế hơn đối với môi trường của bạn, chẳng hạn như khi bạn đang chạy sổ ghi chép kiểu Jupyter tại Google Colaboratory. Môi trường sổ ghi chép Colab rất phù hợp để thực hiện khám phá dữ liệu hợp tác Một sổ ghi chép điển hình đi kèm với nhiều gói khoa học dữ liệu được cài đặt, bao gồm NumPy, Pandas và Matplotlib và bạn có thể thêm các gói mới bằng 155. Nhưng bạn cũng có thể kích hoạt cài đặt tự độngVì 186 không có sẵn cục bộ trên máy chủ Colab nên mã này được sao chép vào ô đầu tiên của sổ ghi chépThí dụ. Nhập tệp dữ liệuVí dụ cuối cùng trong phần này được lấy cảm hứng từ bài đăng trên blog tuyệt vời của Aleksey Bilogur Nhập hầu hết mọi thứ bằng Python. Giới thiệu về Trình tải và Trình tìm mô-đun. Bạn đã biết cách sử dụng 417 để nhập tệp dữ liệu. Tại đây, thay vào đó, bạn sẽ triển khai trình tải tùy chỉnh có thể nhập trực tiếp tệp CSVTrướ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ố. Để làm cho ví dụ về trình tải tùy chỉnh dễ quản lý hơn, hãy xem xét tệp 188 nhỏ hơn sau đây 25Dòng đầu tiên là tiêu đề đặt tên cho ba trường và hai hàng dữ liệu tiếp theo, mỗi hàng chứa thông tin về một nhân viên. Để biết thêm thông tin về cách làm việc với tệp CSV, hãy xem Đọc và ghi tệp CSV bằng Python Mục tiêu của bạn trong phần này là viết một công cụ tìm và một trình tải cho phép bạn nhập tệp CSV trực tiếp để bạn có thể viết mã như sau >>> 26Công việc của công cụ tìm sẽ là tìm kiếm và nhận dạng các tệp CSV. Công việc của trình tải sẽ là nhập dữ liệu CSV. Thông thường, bạn có thể triển khai các trình tìm và trình tải tương ứng trong một lớp chung. Đó là cách tiếp cận bạn sẽ thực hiện ở đây 27Có khá nhiều mã trong ví dụ này. May mắn thay, hầu hết công việc được thực hiện trong 151 và 190. Hãy xem xét chúng chi tiết hơnNhư bạn đã thấy trước đó, 151 chịu trách nhiệm tìm mô-đun. Trong trường hợp này, bạn đang tìm tệp CSV, vì vậy bạn tạo tên tệp có hậu tố 192. 159 chứa tên đầy đủ của mô-đun được nhập. Ví dụ: nếu bạn sử dụng 194, thì 159 sẽ là 196. Trong trường hợp này, tên tệp sẽ là 188Đối với nhập cấp cao nhất, 198 sẽ là 153. Trong trường hợp đó, bạn tìm tệp CSV trong đường dẫn nhập đầy đủ, đường dẫn này sẽ bao gồm thư mục làm việc hiện tại. Nếu bạn đang nhập tệp CSV trong một gói, thì 198 sẽ được đặt thành đường dẫn hoặc nhiều đường dẫn của gói. Nếu bạn tìm thấy tệp CSV phù hợp, thì thông số mô-đun sẽ được trả về. Thông số mô-đun này yêu cầu Python tải mô-đun bằng cách sử dụng 301Dữ liệu CSV được tải bởi 190. Bạn có thể sử dụng 303 từ thư viện chuẩn để thực hiện phân tích cú pháp tệp thực tế. Giống như hầu hết mọi thứ trong Python, các mô-đun được hỗ trợ bởi từ điển. Bằng cách thêm dữ liệu CSV vào 304, bạn cung cấp dữ liệu đó dưới dạng thuộc tính của mô-đunChẳng hạn, thêm 305 vào từ điển mô-đun ở dòng 44 cho phép bạn liệt kê các tên trường trong tệp CSV như sau>>> 28Nói chung, tên trường CSV có thể chứa khoảng trắng và các ký tự khác không được phép trong tên thuộc tính Python. Trước khi thêm các trường làm thuộc tính trên mô-đun, bạn làm sạch tên trường bằng biểu thức chính quy. Điều này được thực hiện trong 306 bắt đầu từ dòng 51Bạn có thể xem ví dụ về hiệu ứng này trong tên trường 307 ở trên. Nếu xem tệp CSV gốc, bạn sẽ thấy tiêu đề có nội dung 308 với dấu cách thay vì dấu gạch dướiBằng cách kết nối 301 này vào hệ thống nhập Python, bạn sẽ nhận được khá nhiều chức năng miễn phí. Ví dụ: bộ đệm mô-đun sẽ đảm bảo rằng tệp dữ liệu chỉ được tải một lầnMẹo và thủ thuật nhập khẩuĐể 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. Bạn sẽ thấy cách xử lý các gói bị thiếu, nhập theo chu kỳ và thậm chí cả các gói được lưu trữ bên trong tệp ZIP Xử lý các gói trên các phiên bản PythonĐôi khi bạn cần xử lý các gói có tên khác nhau tùy thuộc vào phiên bản Python. Bạn đã thấy một ví dụ về điều này. 417 chỉ khả dụng kể từ Python 3. 7. Trong các phiên bản Python cũ hơn, bạn cần cài đặt và sử dụng 421 để thay thếMiễn là các phiên bản khác nhau của gói tương thích, bạn có thể xử lý vấn đề này bằng cách đổi tên gói thành 312 15Trong phần còn lại của mã, bạn có thể tham khảo 313 và không phải lo lắng về việc bạn đang sử dụng 417 hay 421Thông thường, cách dễ nhất là sử dụng câu lệnh 153 để tìm ra phiên bản nào sẽ sử dụng. Một tùy chọn khác là kiểm tra phiên bản của trình thông dịch Python. Tuy nhiên, điều này có thể thêm một số chi phí bảo trì nếu bạn cần cập nhật số phiên bảnBạn có thể viết lại ví dụ trước như sau 00Điều này sẽ sử dụng 417 trên Python 3. 7 trở lên trong khi quay lại 421 trên các phiên bản Python cũ hơn. Xem dự án 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ạyXử lý các gói bị thiếu. Sử dụng một thay thếTrường hợp sử dụng sau có liên quan chặt chẽ với ví dụ trước. Giả sử có một gói triển khai lại tương thích. 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. Tuy nhiên, gói ban đầu có sẵn dễ dàng hơn và cũng mang lại hiệu suất chấp nhận được Một ví dụ như vậy là 320, đây là phiên bản được tối ưu hóa của 321 từ thư viện chuẩn. 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 đó 01This will use 320 if it’s available and fall back to 321 if notAnother similar example is the UltraJSON package, an ultrafast JSON encoder and decoder that can be used as a replacement for 196 in the standard library 02By renaming 325 to 196, you don’t have to worry about which package was actually importedHandle Missing Packages. Use a Mock InsteadA 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 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 mainly consists of special string constants that add color when printed >>> 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 328. Setting 329 to 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 329 be 332 and add 333 to the beginning of your script. The following colors are available>>> 04You can also use 334 to control the style of your text. You can choose between 335, 336, and 337Finally, 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 339 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. Để tránh thêm một phần phụ thuộc khác vào ứng dụng của mình, bạn chỉ muốn sử dụng Colorama nếu ứng dụng này có sẵn trên hệ thống và không phá vỡ ứng dụng nếu ứng dụng không có 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 >>> 06This doesn’t quite work, because 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 177 on 342 objects. However, in this case, it’s more convenient to write your own mock 07 343 is an empty string that will also return the empty string when it’s called. This effectively gives us a reimplementation of Colorama, just without the colorsThe final trick is that 344 returns itself, so that all colors, styles, and cursor movements that are attributes on 345, 346, 347, and 348 are mocked as wellThe 349 module is designed to be a drop-in replacement for Colorama, so you can update the countdown example using search and replace 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 Import Scripts as ModulesOne 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 350 or imported with 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 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 353 file 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 354 is a script that uses the 196 library to format JSON in a more readable fashion 10Now the structure of the JSON file becomes much less complicated to grasp. You can use the 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 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 11If you run this file, then you’ll see that 125 is set to the special value 126 12However, if you import the module, then 125 is set to the name of the module>>> 13This behavior is leveraged in the following pattern 14Let’s use this in a bigger example. In an attempt to keep you young, the following script will replace any “old” age ( 361 or above) with 129 15You can run this as a script, and it will interactively make the age you type younger 16You can also use the module as an importable library. The 124 test on line 12 makes sure that there are no side effects when you import the library. Only the functions 364 and 365 are defined. You can, for instance, use this library as follows>>> 17Without the protection of the 124 test, the import would have triggered the interactive 367 and made 368 very hard to use as a libraryRun Python Scripts From ZIP FilesA slightly obscure feature of Python is that it can run scripts packaged into ZIP files. Ư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. If you want to distribute your Python application as a stand-alone executable file, then see Using PyInstaller to Easily Distribute Python Applications If you give the Python interpreter a ZIP file, then it’ll look for a file named 455 inside the ZIP archive, extract it, and run it. As a basic example, create the following 455 file 18This will print a message when you run it 19Now add it to a ZIP archive. You may be able to do this on the command line 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 126 isn’t a very descriptive name, you named the ZIP file 372. Bây giờ bạn có thể gọi nó trực tiếp bằng Python 21Lưu ý rằng tập lệnh của bạn biết rằng nó nằm bên trong 372. Hơn nữa, gốc của tệp ZIP của bạn được thêm vào đường dẫn nhập của Python để tập lệnh của bạn có thể nhập các mô-đun khác trong cùng một tệp ZIPNghĩ lại ví dụ trước đó mà bạn đã tạo một bài kiểm tra dựa trên dữ liệu dân số. Có thể phân phối toàn bộ ứng dụng này dưới dạng một tệp ZIP. 417 sẽ đảm bảo tệp dữ liệu được trích xuất từ kho lưu trữ ZIP khi cầnThe app consists of the following files 22Bạn có thể thêm chúng vào tệp ZIP giống như cách bạn đã làm ở trên. Tuy nhiên, Python đi kèm với một công cụ có tên là 375 hợp lý hóa quy trình đóng gói các ứng dụng vào kho lưu trữ ZIP. Bạn sử dụng nó như sau 23Lệnh này về cơ bản thực hiện hai việc. nó tạo ra một điểm vào và đóng gói ứng dụng của bạn Hãy nhớ rằng bạn cần tệp 455 làm điểm vào bên trong kho lưu trữ ZIP của mình. Nếu bạn cung cấp cho tùy chọn 458 thông tin về cách bắt đầu ứng dụng của bạn, thì 375 sẽ tạo tệp này cho bạn. In this example, the generated 455 looks like this 24This 455 is packaged, along with the contents of the 381 directory, into a ZIP archive named 382. The 383 suffix signals that this is a Python file wrapped into a ZIP archiveNote. By default, 375 doesn’t compress any files. It only packages them into a single file. You can tell 375 to compress the files as well by adding the 386 optionHowever, this feature is available only in Python 3. 7 and later. See the 375 documentation for more informationOn Windows, 383 files should already be registered as Python files. On Mac and Linux, you can have 375 create executable files by using the 390 interpreter option and specifying which interpreter to use 25The 390 option adds a shebang ( 392) that tells the operating system how to run the file. Additionally, it makes the 383 file executable so that you can run the file just by typing its name 26Notice the 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 395, or if you’re using Windows, then you should be able to use only the filename. 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 437 directory. This is due to a limitation in 398A workaround is to supply the absolute path to 382. On Mac and Linux, you can do this with the following trick 27The 300 command expands to the path of the current directoryLet’s close this section by looking at a nice effect of using 417. Remember that you used the following code to open the data file 28A more common way to open data files is to locate them based on your module’s 413 attribute 29This approach usually works well. However, it falls apart when your application is packed into a ZIP file 30Your data file is inside the ZIP archive, so 430 isn’t able to open it. 417, on the other hand, will extract your data to a temporary file before opening itHandle Cyclical ImportsA cyclical import happens when you have two or more modules importing each other. More concretely, imagine that the module 305 uses 306 and the module 307 similarly imports 305Python’s import system is to some extent designed to handle import cycles. For instance, the following code—while not very useful—runs fine 31Trying to import 305 in the interactive interpreter imports 307 as well>>> 32Note that 307 is imported in the middle of the import of 305, precisely at the 306 statement in the source code of 305. The reason this doesn’t end up in endless recursion is our old friend the module cacheWhen you type 315, a reference to 305 is added to the module cache even before 305 is loaded. When 307 tries to import 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 33Importing 305 works the same as before>>> 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 321 35Now Python gets confused by the import >>> 36The error message may seem a bit puzzling at first. Looking back at the source code, you can confirm that 130 is defined in the 305 moduleThe problem is that 130 isn’t defined in 305 at the time 307 gets imported. Consequently, 327 is used by the call to 328To add to the confusion, you’ll have no issues importing 307>>> 37By the time 307 calls 328, 305 is fully imported and 327 is well defined. As a final twist, because of the module cache you saw earlier, 315 might work if you do some other imports first>>> 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, 306 is done inside 328. This has two consequences. First, 307 is available only inside the 328 function. More importantly, the import doesn’t happen until you call 328 after 305 has been fully imported 39Now there are no issues importing and using 305>>> 40Notice that 307 is, in fact, not imported until you call 328. For another perspective on cyclical imports, see Fredrik Lundh’s classic noteProfile ImportsOne 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 Since the release of 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 344 command-line option, which measures and prints how much time each module takes to import 41The 345 column shows the cumulative time of import (in microseconds) on a per-package basis. You can read the listing as follows. Python spent 346 microseconds to fully import 347, which involved importing 138, 49, and the C implementation 350 as wellThe 351 column shows the time it took to import only the given module, excluding any recursive imports. You can see that 138 took 353 microseconds to import, 49 took 355, 350 took 357, and the import of 347 itself took 359 microseconds. All in all, this adds up to a cumulative time of 346 microseconds (within rounding errors)Have a look at the 361 example from the Colorama section 42In this example, importing 349 took almost 0. 013 seconds. Most of that time was spent importing Colorama and its dependencies. The 351 column shows the import time excluding nested importsFor an extreme example, consider the 124 singleton from earlier. Because it’s loading a big data file, it’s extremely slow to import. To test this, you can run 365 as a script with the 386 option 43Trong trường hợp này, mất gần 2 giây để nhập 124, trong đó khoảng 1. 6 giây được sử dụng trong chính mô-đun, chủ yếu để tải tệp dữ liệu 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 CodeConclusionIn 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
Throughout the tutorial, you’ve seen many links to further info. The most authoritative source on the Python import system is the official documentation
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 Send Me Python Tricks » 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 Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas Level Up Your Python Skills » Bạn nghĩ sao? 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 |