Đối với hầu hết các lập trình viên mới bắt đầu và trung cấp, đôi khi làm việc với nhiều thư mục trong các dự án Python có thể gây khó chịu. Là một lập trình viên Python, cách tốt nhất là trừu tượng hóa mã ứng dụng thành các tệp và thư mục khác nhau và theo các yêu cầu dữ liệu và chức năng liên quan của chúng. Hơn nữa, bạn sẽ không có tùy chọn nào ngoài việc sử dụng các gói và mô-đun hiện có mà người khác đã viết. Điều này sẽ yêu cầu khả năng làm việc hiệu quả trong nhiều gói thư mục trong dự án của bạn
Tầm quan trọng của việc làm việc với các thư mục đa cấp trong mã dự án của bạn
- Tính mô đun của mã. Để viết giải pháp cho các vấn đề lớn hơn, điều quan trọng là phải chia dự án của bạn thành các phần nhỏ hơn, trong đó mỗi vấn đề nhỏ hơn được triển khai trong một thư mục con riêng biệt trong dự án của bạn. Điều này sẽ cho phép bạn tập trung vào các bài toán con nhỏ hơn, ít gây choáng ngợp hơn và dễ giải quyết hơn.
- Khả năng sử dụng lại mã. Điều quan trọng là mã dự án của bạn phải tuân theo nguyên tắc DRY [Don't Repeat Yourself]. Khi bạn tìm thấy nhiều phần mã về cơ bản đang cố gắng làm điều tương tự, có điều gì đó không đúng. Khi bạn trừu tượng hóa mã của mình bằng cách triển khai logic đơn lẻ hoặc có liên quan vào các mô-đun và gói con riêng lẻ, thì bạn có thể sử dụng chúng ở bất kỳ đâu trong dự án của mình bằng cách chỉ nhập chúng thay vì cố gắng viết lại chúng ở nơi khác trong dự án của bạn
- Khả năng bảo trì của mã. Đây có lẽ là lý do quan trọng nhất để thực hiện trừu tượng hóa mã. Điều rất quan trọng là các phần mã dự án của bạn phải được kết hợp lỏng lẻo với nhau. Khi bạn phải sửa đổi một số phần trong mã dự án của mình chỉ vì bạn đã thay đổi một phần nhỏ trong dự án của mình, thì chắc chắn có điều gì đó không ổn. Mã dự án của bạn không cần quá phụ thuộc lẫn nhau. Sự phụ thuộc lẫn nhau nên được giữ ở mức tối thiểu nhất. Mã dự án tốt sẽ cho phép bất kỳ ai không có kiến thức bên ngoài dự án dễ dàng thực hiện các thay đổi đối với nó. Điều này sẽ giúp ích trong quá trình hợp tác nhóm. Khi bạn sử dụng tốt các gói con và mô-đun, bạn chỉ phải thay đổi mô-đun cụ thể mà bạn cần thay đổi
Tuy nhiên, làm việc với nhiều cấp thư mục trong một dự án có thể gây khó khăn cho các lập trình viên mới bắt đầu và sử dụng các gói hoặc mô-đun của bên thứ ba trong các chương trình của riêng họ. Trong bài viết này, tôi cung cấp một cách đơn giản để dễ dàng xử lý việc nhập tệp trong mã dự án thư mục đa cấp. [Để biết cách cấu trúc các dự án Python, hãy tham khảo tài liệu Python ở cuối bài này. ]
Nhập tệp trong cấu trúc thư mục đa cấp
Theo cú pháp Python, dấu chấm ở đầu biểu thị thư mục hiện tại. Mỗi dấu chấm bổ sung sẽ đưa bạn lên một thư mục hoặc gói cao hơn. Thông thường, nên sử dụng nhập tuyệt đối thay vì nhập tương đối trong mã của bạn
Hãy sử dụng một dự án Python có cấu trúc thư mục [như hình bên dưới] để chứng minh việc nhập từ một thư mục đa cấp dễ dàng như thế nào bằng cách sử dụng cả nhập tuyệt đối và tương đối
Ghi chú. Trong Python, mỗi thư mục hoặc thư mục con phải được khởi tạo bằng __init__. py để nó được công nhận là gói hoặc gói con. Nếu không, bạn có thể gặp lỗi không tìm thấy mô-đun khi cố gắng nhập
Khi ở trong thư mục myPackage và để truy cập bảo mật. tệp py trong __init__. py của myPackage trong cùng thư mục
import security #absolute import from . import security #relative import
Tuy nhiên, đối với tệp sâu hơn một cấp, khi ở trong __init__. py của myPackage và nhập mục. py trong thư mục con1
import subfolder1.item #absolute import from subfolder1 import item #absolute import
Đối với tệp sâu hơn hai cấp độ, khi ở trong __init__. py của myPackage và nhập người dùng. py từ thư mục con2
import folder1.folder2.user #absolute import from folder1.folder2 import user #absolute import
Khía cạnh khó khăn nhất là phải nhập ngược một tệp—tức là, từ cấp cao hơn vào một tệp trong thư mục cấp thấp hơn. Nhập tuyệt đối làm cho điều này dễ dàng hơn
Để truy cập bảo mật. py từ sinh viên. py của thư mục con2
import myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import
Để truy cập tài khoản. py trong thư mục con3 từ người dùng. py trong thư mục con2
import myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import
Để truy cập người dùng. py từ sinh viên. py trong cùng thư mục con2, chỉ cần
import user # python3 from . import user # any python version
Tóm tắt mã của bạn thành các gói con hoặc mô-đun sẽ giúp bạn viết mã dễ bảo trì. Tôi hy vọng điều này sẽ giúp giảm đau đầu khi làm việc trong gói hoặc mô-đun thư mục đa cấp
Trước khi chúng tôi bắt đầu, hãy hiểu sự khác biệt giữa gói và mô-đun vì chúng tôi sẽ tạo một số tài liệu tham khảo về những điều này trong suốt bài viết
Hãy bắt đầu nàomô-đun. Một kịch bản python duy nhất
Bưu kiện. Bộ sưu tập các mô-đun
Cấu trúc thư mục trong hình trên trông hơi phức tạp và tôi sẽ không yêu cầu bạn tạo tất cả cùng một lúc
Để đơn giản hóa mọi thứ, trước tiên hãy tạo một thư mục duy nhất
#example2.pyimport example1 as e1# imported string3 trong thư mục dự án của chúng ta và thêm hai mô-đun vào đó —
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
#example2.pyimport example1 as e1# imported string4 và
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
#example2.pyimport example1 as e1# imported string5
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
Ý tưởng là có bất kỳ chức năng/biến/lớp nào được xác định trong
#example2.pyimport example1 as e1# imported string4 để có thể truy cập được trong
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
#example2.pyimport example1 as e1# imported string5. Nội dung của mô-đun như sau
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
import subfolder1.item #absolute import from subfolder1 import item #absolute import1
Để nhập những mặt hàng này trong vòng
#example2.pyimport example1 as e1# imported string5
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
import subfolder1.item #absolute import from subfolder1 import item #absolute import3
Đầu ra từ việc chạy ví dụ2. py
Chỉ cần lặp lại những gì rõ ràng đáng chú ý, các mục trong mô-đun đã nhập có thể được truy cập bằng cách sử dụng ký hiệu dấu chấm — ví dụ:
#example2.pyimport example1 as e1# imported string9 hoặc
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
import subfolder1.item #absolute import from subfolder1 import item #absolute import50. Nếu bạn từng cảm thấy việc viết
import subfolder1.item #absolute import from subfolder1 import item #absolute import51 mỗi lần có vẻ hơi dài, chúng ta có thể sử dụng bí danh bằng cách sử dụng
import subfolder1.item #absolute import from subfolder1 import item #absolute import52 và viết lại
#example2.pyimport example1 as e1# imported string5 như sau. Như bạn đã đoán đúng, đầu ra sẽ vẫn giữ nguyên
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
#example2.pyimport example1 as e1# imported string
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
Chính xác thì điều gì sẽ xảy ra khi chúng ta viết một câu lệnh 'nhập khẩu'?
Trình thông dịch python cố gắng tìm thư mục chứa mô-đun mà chúng tôi đang cố gắng nhập vào
import subfolder1.item #absolute import from subfolder1 import item #absolute import54. Đó là danh sách các thư mục mà Python sẽ tìm kiếm sau khi tìm kiếm xong các mô-đun được lưu trong bộ nhớ cache và các mô-đun thư viện chuẩn của Python
Hãy xem đường dẫn hệ thống của chúng ta chứa gì tại thời điểm này [bằng cách nhận xét các dòng mã trước đó trong
#example2.pyimport example1 as e1# imported string5]
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
import subfolder1.item #absolute import from subfolder1 import item #absolute import5
Đầu ra từ sys. con đường
Như bạn có thể thấy, phần tử đầu tiên trong danh sách được trả về bởi
import subfolder1.item #absolute import from subfolder1 import item #absolute import54 trỏ tới thư mục
import subfolder1.item #absolute import from subfolder1 import item #absolute import57, là nơi chứa mô-đun i đã nhập của chúng tôi. e.
#example2.pyimport example1 as e1# imported string4 cư trú. Bây giờ xin lưu ý bạn, không phải ngẫu nhiên mà thư mục này có mặt một cách kỳ diệu trong
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
import subfolder1.item #absolute import from subfolder1 import item #absolute import54
Đầu ra từ
import subfolder1.item #absolute import from subfolder1 import item #absolute import54 sẽ luôn chứa thư mục hiện tại ở chỉ mục 0. Thư mục hiện tại là thư mục chứa tập lệnh đang chạy
Đây là lý do việc nhập khá đơn giản khi cả mô-đun người gọi và mô-đun callee nằm trong cùng một thư mục
Điều gì xảy ra nếu tôi chỉ muốn nhập một số mục chứ không phải tất cả các mục từ mô-đun đã nhập?
Trong ví dụ của chúng tôi, chúng tôi chỉ có một chuỗi và một hàm được xác định trong mô-đun
#example2.pyimport example1 as e1# imported string4. Một điều quan trọng cần nhớ là bất cứ khi nào một câu lệnh nhập được thực hiện, toàn bộ mô-đun sẽ được chạy. Để chứng minh điều này, hãy sửa đổi một chút
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
#example2.pyimport example1 as e1# imported string4
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
import myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import0
Và bây giờ hãy thử chạy
#example2.pyimport example1 as e1# imported string5. Bạn sẽ thấy rằng câu lệnh in cùng với đầu ra từ
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
import myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import04 cũng sẽ được in [ngoài các đầu ra trước đó]
Ghi chú. Có một giải pháp thay thế trong đó chúng ta có thể kiểm soát xem câu lệnh có được chạy hay không khi được nhập. Ví dụ: xem đoạn mã bên dưới
import myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import3
Mã bên trong câu lệnh
import myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import05 sẽ không chạy khi được nhập, nhưng
import myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import06 và
import myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import07 được xác định bên ngoài sẵn sàng để sử dụng thông qua một lần nhập. Phải nói rằng, nếu chúng ta chạy
#example2.pyimport example1 as e1# imported string4 như một mô-đun độc lập, mã trong câu lệnh
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
import myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import09 sẽ được thực thi
Đầu ra từ việc chạy ví dụ1. py
Dù sao đi nữa, bây giờ tôi đã chứng minh rằng việc nhập một mô-đun sẽ chạy tất cả nội dung của nó [nếu không sử dụng
import myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import30], chắc hẳn khá trực quan rằng tại sao chỉ nhập các mục quan tâm lại có ý nghĩa. Hãy xem cách thực hiện việc này trong
#example2.pyimport example1 as e1# imported string5 bằng cách chỉ nhập hàm
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
import myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import32 từ
#example2.pyimport example1 as e1# imported string4. Điều này cũng giúp chúng tôi loại bỏ ký hiệu dấu chấm và chúng tôi chỉ có thể sử dụng hàm
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
import myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import32 nguyên trạng
import myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import4
Tương tự, chúng ta có thể thực hiện
import myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import35 để nhập cả hai đối tượng từ
#example2.pyimport example1 as e1# imported string4
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
Ghi chú. Thông thường, tồn tại các mã bao gồm các câu lệnh nhập chẳng hạn như
import myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import37. Điều này về cơ bản có nghĩa là nhập mọi thứ, tuy nhiên, đây được coi là cách làm không tốt vì nó tác động tiêu cực đến khả năng đọc mã
Nhu cầu về PYTHONPATH là gì?
Nếu bạn từng để ý đến cấu trúc thư mục cho các dự án trên Github, thì thường có một thư mục
import myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import38 chứa một số tập lệnh tiện ích cho các tác vụ phổ biến như tiền xử lý, dọn dẹp dữ liệu, v.v. Chúng được giữ tách biệt với các tập lệnh chính và có nghĩa là được sử dụng lại
Hãy tiếp tục và tạo một cái cho dự án của chúng ta. Gói
import myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import38 sẽ chứa ba mô-đun —
import myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import40,
import myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import41 và
import myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import42 để trả về độ dài, chữ thường và chữ hoa của đầu vào chuỗi, tương ứng
Chúng tôi cũng sẽ tạo mô-đun
import myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import43 ở thư mục gốc của dự án. Đây là nơi chúng tôi sẽ nhập các mô-đun trong gói
import myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import44
Nội dung của ba mô-đun như sau
import user # python3 from . import user # any python version5
Bây giờ, nếu chúng ta phải nhập mô-đun
import myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import40 vào
import myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import43, đây là cách chúng ta thường làm
import user # python3 from . import user # any python version8
Điều quan trọng cần lưu ý là nếu bạn thực hiện ________ 447 thay vì ________ 448, bạn sẽ nhận được ________ 449. Điều này là do danh sách
import subfolder1.item #absolute import from subfolder1 import item #absolute import54 không chứa [chưa] thư mục
import user # python3 from . import user # any python version51 cần thiết để tìm mô-đun
import myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import40. Hãy xem cách chúng ta có thể thêm nó vào danh sách
import subfolder1.item #absolute import from subfolder1 import item #absolute import54
Có hai cách để làm điều này
Phương pháp 1. sử dụng
import user # python3 from . import user # any python version54
#example2.pyimport example1 as e1# imported string7
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
Vài điều cần xem xét
- Thứ tự của
import user # python3 from . import user # any python version
55 rất quan trọng — chỉ khi bạn đã thêm đường dẫn đến thư mụcimport myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import
38 bằng cách sử dụngimport user # python3 from . import user # any python version
54, bạn mới có thể thực thi câu lệnhimport myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import
47.
Tóm lại, đừng để tất cảimport user # python3 from . import user # any python version
59,import user # python3 from . import user # any python version
80 vàimport myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import
47 ở đầu tập lệnh chỉ vì sự gọn gàng. import user # python3 from . import user # any python version
82 trả về đường dẫn tuyệt đối đến thư mục làm việc hiện tại. Chúng tôi sử dụngimport user # python3 from . import user # any python version
83 để thêm thư mụcimport myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import
38 vào đường dẫn này- Như mọi khi, việc truy cập các chức năng được xác định trong mô-đun đã nhập được hỗ trợ bằng cách sử dụng ký hiệu dấu chấm i. e.
import user # python3 from . import user # any python version
85
Phương pháp 2. sử dụng biến môi trường
import user # python3 from . import user # any python version86
Thông thường, tôi thấy việc sửa đổi biến pythonpath dễ dàng hơn là xử lý các thư mục nối thêm bằng Phương pháp 1
PYTHONPATH là một biến môi trường mà bạn có thể đặt để thêm các thư mục bổ sung nơi python sẽ tìm kiếm các mô-đun và gói. [Nguồn]
Trước khi chúng tôi sửa đổi nó, hãy kiểm tra nội dung của nó [để đảm bảo rằng chúng tôi không ghi đè] bằng cách sử dụng
import user # python3 from . import user # any python version87 trong thiết bị đầu cuối
Có vẻ như hiện tại nó trống nhưng trong trường hợp không có, bạn luôn nên sửa đổi pythonpath theo cách mà bạn đang thêm vào nó và không ghi đè lên nó. Cụ thể hơn, bạn phải thêm thư mục mới của mình vào
import user # python3 from . import user # any python version86, được phân tách bằng dấu hai chấm [
import user # python3 from . import user # any python version89] từ nội dung hiện có của nó
Với bộ biến pythonpath, chúng tôi không còn cần phải thêm vào
import subfolder1.item #absolute import from subfolder1 import item #absolute import54in
import myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import43 nữa [Tôi đã nhận xét chúng trong đoạn trích bên dưới cho rõ ràng]
import subfolder1.item #absolute import from subfolder1 import item #absolute import30
Ghi chú. Khi bạn đóng python, danh sách sẽ trở lại các giá trị mặc định trước đó. Nếu bạn muốn thêm vĩnh viễn một thư mục vào
#example2.pyimport example1 as e1# imported string72, hãy thêm lệnh xuất [
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
#example2.pyimport example1 as e1# imported string73] vào
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
#example2.pyimport example1 as e1# imported string74 của bạn. [Xem cuộc thảo luận về StackOverflow này]
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
Cuối cùng, sau khi đã xác định cả hai phương thức, hãy chọn một phương thức [dựa trên tùy chọn/trường hợp sử dụng của bạn] để nhập hai mô-đun còn lại —
import myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import42 và
import myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import41in
import myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import43.
[P. S. Tôi đang đi với Phương pháp 1 chỉ để giải trí. ]
import subfolder1.item #absolute import from subfolder1 import item #absolute import31
siêu. Điều này có vẻ tuyệt vời. Tuy nhiên, sẽ không tuyệt sao nếu chúng ta chỉ có thể thực hiện
#example2.pyimport example1 as e1# imported string78 thay vì nhập tất cả các mô-đun bên trong nó một cách riêng lẻ? . Vì vậy, làm thế nào để chúng ta làm điều đó?
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
Khi nào chúng ta cần __init__. py?
Trước tiên, hãy thử nhập thư mục
import myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import38 trong
import myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import43 [sau khi nhận xét tất cả mã hiện có]
import subfolder1.item #absolute import from subfolder1 import item #absolute import32
Chạy tập lệnh này sẽ không gây ra bất kỳ lỗi nào và đúng như vậy - trình thông dịch sẽ xem bên trong
import subfolder1.item #absolute import from subfolder1 import item #absolute import54 và nó sẽ tìm thấy thư mục hiện tại
import subfolder1.item #absolute import from subfolder1 import item #absolute import302 tại chỉ mục 0. Đây là tất cả những gì nó cần để tìm thư mục
import myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import38
Bây giờ, hãy thử truy cập mô-đun
import myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import40 từ
import myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import38
import subfolder1.item #absolute import from subfolder1 import item #absolute import33
Khi bạn cố chạy tập lệnh này, bạn sẽ thấy một thông báo
import subfolder1.item #absolute import from subfolder1 import item #absolute import306. Theo thuật ngữ thông thường, điều này có nghĩa là chúng tôi sẽ không thể truy cập bất kỳ tập lệnh python nào bên trong
import myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import38đơn giản vì trình thông dịch chưa biết đây là một gói
Chúng tôi có thể biến thư mục này thành một gói bằng cách giới thiệu tệp
import subfolder1.item #absolute import from subfolder1 import item #absolute import308 trong thư mục
import myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import38
Trong vòng
import subfolder1.item #absolute import from subfolder1 import item #absolute import308, chúng tôi nhập tất cả các mô-đun mà chúng tôi cho là cần thiết cho dự án của mình
import subfolder1.item #absolute import from subfolder1 import item #absolute import34
Và hãy gọi nó trong vòng
import myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import43
import subfolder1.item #absolute import from subfolder1 import item #absolute import35
Đợi chút. Tại sao chúng tôi thấy lỗi khi chạy
import subfolder1.item #absolute import from subfolder1 import item #absolute import312?
Trả lời. Cách chúng tôi đã nhập các mô-đun trong
import subfolder1.item #absolute import from subfolder1 import item #absolute import308 ở trên có vẻ hợp lý với bạn — xét cho cùng thì
import subfolder1.item #absolute import from subfolder1 import item #absolute import308 và
import myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import40 [hoặc
import myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import41,
import myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import42] đều ở cùng cấp độ nên không có lý do gì mà
import subfolder1.item #absolute import from subfolder1 import item #absolute import318 không hoạt động. Trên thực tế, nếu bạn tự chạy tệp
import subfolder1.item #absolute import from subfolder1 import item #absolute import319 này, nó sẽ thực thi hoàn hảo [nó sẽ không đưa ra kết quả nào nhưng dù sao cũng sẽ thực thi thành công].
Phải nói rằng, chúng ta không thể sử dụng cách nhập trên vì mặc dù
import myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import40 và
import myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import41 ở cùng cấp độ với
import subfolder1.item #absolute import from subfolder1 import item #absolute import308 nhưng đây không phải là cấp độ mà từ đó
import subfolder1.item #absolute import from subfolder1 import item #absolute import319 sẽ được gọi. Trên thực tế, chúng tôi đang thực hiện cuộc gọi từ
import myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import43 nên
import subfolder1.item #absolute import from subfolder1 import item #absolute import54 sẽ chỉ có thư mục hiện tại của
import myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import43 i. e.
import subfolder1.item #absolute import from subfolder1 import item #absolute import302 để tìm kiếm bên trong bất kỳ hàng nhập khẩu nào. Do đó, khi trình thông dịch gặp lệnh
#example2.pyimport example1 as e1# imported string78 trong
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
import myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import43, mặc dù nó di chuyển đến
import subfolder1.item #absolute import from subfolder1 import item #absolute import308 bên trong thư mục
import myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import38, thì
import subfolder1.item #absolute import from subfolder1 import item #absolute import54 không được cập nhật tự động và trình thông dịch không có cách nào biết tìm mô-đun có tên
import subfolder1.item #absolute import from subfolder1 import item #absolute import333 ở đâu. Bằng cách nào đó chúng ta phải trỏ đến vị trí của thư mục
import myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import38. Để làm như vậy, chúng tôi có thể sử dụng nhập tương đối hoặc tuyệt đối trong
import subfolder1.item #absolute import from subfolder1 import item #absolute import308 [hoặc đặt biến
import user # python3 from . import user # any python version86 như được mô tả ở trên]
Nhập khẩu tương đối [không khuyến nghị]. chỉ định đường dẫn liên quan đến đường dẫn của tập lệnh gọi
import subfolder1.item #absolute import from subfolder1 import item #absolute import36
Chúng tôi sử dụng ký hiệu dấu chấm [
import subfolder1.item #absolute import from subfolder1 import item #absolute import337 hoặc
import subfolder1.item #absolute import from subfolder1 import item #absolute import338] để chỉ định nhập khẩu tương đối. Dấu chấm đơn trước Lower đề cập đến cùng thư mục với thư mục mà quá trình nhập được gọi. Điều này có thể được hình dung như nhập
import subfolder1.item #absolute import from subfolder1 import item #absolute import339 từ
import subfolder1.item #absolute import from subfolder1 import item #absolute import340. Tương tự, hai dấu chấm trước tên mô-đun có nghĩa là tăng hai cấp so với cấp hiện tại
Nhập khẩu tuyệt đối [lựa chọn tốt hơn]. chỉ định đường dẫn tuyệt đối của mô-đun đã nhập từ thư mục gốc của dự án [hoặc bất kỳ thư mục nào khác mà sys. đường dẫn có quyền truy cập vào]
import subfolder1.item #absolute import from subfolder1 import item #absolute import37
Bây giờ, điều này chứa nhiều thông tin hơn so với nhập khẩu tương đối và ít bị phá vỡ hơn. Ngoài ra,
import subfolder1.item #absolute import from subfolder1 import item #absolute import54 có quyền truy cập vào thư mục gốc của dự án i. e.
import subfolder1.item #absolute import from subfolder1 import item #absolute import302 như đã giải thích ở trên và từ đó có thể dễ dàng tìm kiếm thư mục
import myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import38. [Tại sao? Bởi vì nó là thư mục con trực tiếp của gốc dự án]
Điều gì xảy ra khi chúng tôi nhập một gói có _____1344 được xác định? . Cho rằng chúng tôi thực hiện tất cả các nhập cần thiết ở đây, mã sạch hơn nhiều trong tập lệnh gọi. Ví dụ
import subfolder1.item #absolute import from subfolder1 import item #absolute import38
Thật tuyệt vời. Bây giờ chúng tôi đã chuyển đổi thư mục
import myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import38 của mình thành một gói. Cái hay của gói này là nó có thể được nhập ở bất cứ đâu và sử dụng gần như ngay lập tức. Hãy xem cách chúng ta có thể sử dụng gói này bên trong thư mục
#example2.pyimport example1 as e1# imported string3. Hãy tiếp tục và tạo một tệp mới có tên là
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
import subfolder1.item #absolute import from subfolder1 import item #absolute import347 trong
#example2.pyimport example1 as e1# imported string3
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
import subfolder1.item #absolute import from subfolder1 import item #absolute import39
Vài điều cần xem xét
- Trước khi nhập gói
import myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import
38, chúng tôi phải đảm bảo thư mục mẹ củaimport myPackage.security #absolute import from myPackage import security #absolute import from .. import security #relative import
38 i. e. root dự án có thể truy cập được bằng trình thông dịch Python. Sẽ là thiếu thận trọng khi cho rằng nó sẽ xảy ra theo mặc định, chủ yếu là do chúng tôi hiện đang ở một cấp trong thư mục gốc của dự án [chúng tôi đang chạy tập lệnh từimport subfolder1.item #absolute import from subfolder1 import item #absolute import
351],import subfolder1.item #absolute import from subfolder1 import item #absolute import
54 sẽ cóimport subfolder1.item #absolute import from subfolder1 import item #absolute import
353 ở chỉ mục 0 import user # python3 from . import user # any python version
82 sẽ cung cấp tên của thư mục cho tập lệnh hiện tại vàimport subfolder1.item #absolute import from subfolder1 import item #absolute import
355 sẽ cung cấp đường dẫn đến thư mục mẹ bằng ký hiệu dấu chấm i. e.import subfolder1.item #absolute import from subfolder1 import item #absolute import
338. Nói chung,import subfolder1.item #absolute import from subfolder1 import item #absolute import
357 sẽ cung cấp đường dẫn tuyệt đối đến thư mục gốc của dự án
Thưởng. Chúng tôi thậm chí có thể thêm các mô-đun từ các thư mục khác vào
import subfolder1.item #absolute import from subfolder1 import item #absolute import308 của chúng tôi. Chẳng hạn, hãy mang vào
import subfolder1.item #absolute import from subfolder1 import item #absolute import359 được xác định trong
import subfolder1.item #absolute import from subfolder1 import item #absolute import360
#example2.pyimport example1 as e1# imported string0
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
Gọi chức năng này trong
import subfolder1.item #absolute import from subfolder1 import item #absolute import347
#example2.pyimport example1 as e1# imported string1
print["The imported string is: ", e1.MY_EX1_STRING]# imported function
e1.yolo[10]
Phần kết luận
Thành thật mà nói, các lỗi nhập khẩu từng thực sự khiến tôi phát hoảng lúc đầu vì đây là một lĩnh vực mà tôi không bao giờ phải bận tâm. Qua nhiều năm, tôi đã học được một mẹo hữu ích — đối với bất kỳ gói/mô-đun nào bạn đang cố gắng nhập bằng cách sử dụng
import subfolder1.item #absolute import from subfolder1 import item #absolute import362, hãy đảm bảo trình thông dịch Python có quyền truy cập vào gói/mô-đun đó. Nếu không, hãy cập nhật
import subfolder1.item #absolute import from subfolder1 import item #absolute import54 hoặc thậm chí tốt hơn là thêm thư mục có liên quan vào biến
import user # python3 from . import user # any python version86 và tránh phải xử lý nó trong tập lệnh của bạn
Như mọi khi, nếu có một cách dễ dàng hơn để thực hiện/giải thích một số nội dung được đề cập trong bài viết này, hãy cho tôi biết. Nói chung, hãy kiềm chế những bình luận phá hoại/rác rưởi/thù địch không được yêu cầu
Cho đến lần sau ✨
Tôi thích viết hướng dẫn từng bước cho người mới bắt đầu, hướng dẫn cách thực hiện, câu hỏi phỏng vấn, giải mã thuật ngữ được sử dụng trong ML/AI, v.v. Nếu bạn muốn có toàn quyền truy cập vào tất cả các bài viết của tôi [và các tác giả khác trên Phương tiện], thì bạn có thể đăng ký bằng liên kết của tôi tại đây