Đặt đoạn mã này ở đầu bất kỳ tệp Python nào không phải là cấp cao nhất trong dự án của bạn để nhập để gọi mã từ các thư mục khác
Đoạn trích
if __name__ == '__main__': import os import sys sys.path.append[os.getcwd[]]
Mục đích
Dự án này nhằm mục đích làm ví dụ về cách nhập các gói anh chị em khi phát triển bằng Python. Nó dựa trên 3. 6. 8, tôi tin rằng nó sẽ hoạt động trên mọi thứ trên Python 3. 3 dựa trên Ghi chú của Nick Coghlan
Tôi không có cách nào khẳng định đây là "Pythonic" hay đúng cách để làm cho nó hoạt động, nhưng tôi đã có thể làm cho nó hoạt động ổn định cho các nỗ lực phát triển khác của mình và nghĩ rằng những người khác có thể thấy ví dụ này hữu ích
Python có tài liệu về cách xử lý quá trình nhập, nhưng tôi thấy các ví dụ này không hữu ích trong quá trình phát triển dự án. Các ví dụ sử dụng đường dẫn tuyệt đối dường như cho rằng bạn đang thử nghiệm từ cấp cao nhất của dự án và không chạy các mô-đun riêng lẻ gọi một mô-đun được tìm thấy trong thư mục khác. Ngoài ra còn có các ví dụ về Nhập khẩu tương đối, tuy nhiên, đây dường như chỉ là một cách để tránh đánh vần đường dẫn đầy đủ của các mô-đun của bạn và không phải là thứ bạn có thể tận dụng trong quá trình phát triển
Dự án mẫu
Bao gồm bên dưới là bố cục dự án và các ví dụ về nơi bạn sẽ chèn đoạn mã từ phía trên. Dự án này cũng chứa các tệp để bạn có thể tự kiểm tra kết quả của việc này
python-sibling-import/ top_level.py sound/ second_level.py effects/ echo.py formats/ wav_write.py {snippet} {your code}
from sub1.helper import helper
from sub2.utils import some_func
3 có thể gọi xuống các gói thấp hơn mà không gặp sự cố. Tuy nhiên, nếu bạn muốn chạy from sub1.helper import helper
from sub2.utils import some_func
4 với lệnh gọi tới from sub1.helper import helper
from sub2.utils import some_func
5, điều này yêu cầu thực hiện thêm công việc để thực hiện chức năng. Bạn có thể sử dụng Đoạn trích từ phía trên ở đầu mã cấp thấp hơn của mình để chạy riêng lẻ và vẫn tận dụng được nội dung được viết trong thư mục khácLàm thế nào nó hoạt động
Điều này tận dụng chức năng HĐH Python để lấy Thư mục làm việc hiện tại. Khi nó có thư mục làm việc hiện tại của bạn, nó sẽ thêm nó vào Đường dẫn hệ thống, đây là một biến chứa tất cả các vị trí tìm kiếm cho các gói/mô-đun sẽ được tải. Khi tải các gói khác trong dự án của bạn, nó sẽ xử lý chúng như thể bạn đang làm việc từ thư mục cấp cao nhất
Đoạn trích giả định rằng bạn đang mở dự án này trong môi trường phát triển của mình từ cấp cao nhất hoặc gốc của dự án và có thể không hoạt động theo cách khác. Để sửa đổi mã được mở từ cấp thấp hơn của gói, chẳng hạn như trong
from sub1.helper import helper
from sub2.utils import some_func
6 trong Âm thanh thay vì PYTHON-SIBLING-IMPORT, cần phải sửa đổi các câu lệnh nhập để loại bỏ việc bao gồm from sub1.helper import helper
from sub2.utils import some_func
7 Sở thích của tôi là sử dụng bố cục dự án sau đây, trong đó
from sub1.helper import helper
from sub2.utils import some_func
3 và from sub1.helper import helper
from sub2.utils import some_func
4 là các gói con độc lậpproject/
main.py
sub1/
__init__.py
helper.py
sub2/
__init__.py
utils.py
tests/
__init__.py
test_sub1.py
test_sub2.py
Các tệp bên dưới
from sub1.helper import helper
from sub2.utils import some_func
5 được sử dụng để kiểm tra từng gói/mô-đun. Chúng tôi có thể nhập từ mỗi gói như dưới đâyfrom sub1.helper import helper
from sub2.utils import some_func
Chạy một mô-đun thử nghiệm duy nhất
Để chạy một mô-đun thử nghiệm, trong trường hợp này là
from sub1.helper import helper
from sub2.utils import some_func
6________số 8
Lưu ý rằng lệnh này đang chạy từ thư mục
from sub1.helper import helper
from sub2.utils import some_func
7, không phải bên trong thư mục from sub1.helper import helper
from sub2.utils import some_func
8. Ngoài ra, hãy cẩn thận rằng đó là from sub1.helper import helper
from sub2.utils import some_func
9, không phải $ python -m tests.test_sub1
0. Điều này là để tham chiếu một mô-đun thử nghiệm giống như cách bạn nhập nóChạy một trường hợp thử nghiệm hoặc phương pháp thử nghiệm
Ngoài ra, bạn có thể chạy một TestCase hoặc một phương pháp thử nghiệm duy nhất
python-sibling-import/ top_level.py sound/ second_level.py effects/ echo.py formats/ wav_write.py {snippet} {your code}3
Chạy tất cả các bài kiểm tra
Một cách là sử dụng
$ python -m tests.test_sub1
1 được đề cập trong Cấu trúc thư mục điển hình để chạy thử nghiệm bằng cách sử dụng unittest, như được sao chép bên dướipython-sibling-import/ top_level.py sound/ second_level.py effects/ echo.py formats/ wav_write.py {snippet} {your code}5
Điều này sẽ chạy tất cả các bài kiểm tra *. mô-đun py bên trong gói
from sub1.helper import helper
from sub2.utils import some_func
8Ngoài ra, chúng ta có thể cài đặt pytest. Sau đó để chạy tất cả các bài kiểm tra
python-sibling-import/ top_level.py sound/ second_level.py effects/ echo.py formats/ wav_write.py {snippet} {your code}7
Tùy chọn thứ hai ngắn gọn hơn tùy chọn thứ nhất
Chạy một mô-đun trong gói con
Để chạy một mô-đun bên trong gói con, trong trường hợp này là
$ python -m tests.test_sub1
3. chúng tôi không thể sử dụngpython-sibling-import/ top_level.py sound/ second_level.py effects/ echo.py formats/ wav_write.py {snippet} {your code}9
Thay vào đó, chúng ta nên sử dụng kỹ thuật tương tự như chạy mô-đun thử nghiệm
from sub1.helper import helper
from sub2.utils import some_func
0Nhập từ một thư mục anh chị em
Đôi khi, chúng tôi có thể muốn nhập một mô-đun/phương thức từ thư mục anh chị em. Ví dụ:
$ python -m tests.test_sub1
4 muốn nhập $ python -m tests.test_sub1
5. Sử dụngfrom sub1.helper import helper
from sub2.utils import some_func
3Sau đó, hãy nhớ chạy
$ python -m tests.test_sub1
4 dưới dạng mô-đun, như đã đề cập ở trênNhập từ thư mục mẹ
Xem xét cách bố trí sau,
$ python -m tests.test_sub1
7 được sử dụng bởi hầu hết các tệp nguồn. Ví dụ: $ python -m tests.test_sub1
4 muốn nhập $ python -m tests.test_sub1
7 từ thư mục mẹfrom sub1.helper import helper
from sub2.utils import some_func
8Trong
python-sibling-import/ top_level.py sound/ second_level.py effects/ echo.py formats/ wav_write.py {snippet} {your code}30, chúng tôi không thể trực tiếp sử dụng
from sub1.helper import helper
from sub2.utils import some_func
0Tùy chọn một là thêm một
python-sibling-import/ top_level.py sound/ second_level.py effects/ echo.py formats/ wav_write.py {snippet} {your code}31 bên dưới
python-sibling-import/ top_level.py sound/ second_level.py effects/ echo.py formats/ wav_write.py {snippet} {your code}32 để chuyển đổi dự án gốc thành một gói và chạy
python-sibling-import/ top_level.py sound/ second_level.py effects/ echo.py formats/ wav_write.py {snippet} {your code}33 từ bên ngoài thư mục
from sub1.helper import helper
from sub2.utils import some_func
7. Tuy nhiên, có một số nhược điểm. Đầu tiên, thật bất tiện khi gọi từ bên ngoài với một lệnh dài như vậy. Thứ hai, điều này giả định rằng dự án gốc là một gói, điều này không phải lúc nào cũng đúngTùy chọn hai là tạo một virtualenv và sử dụng
python-sibling-import/ top_level.py sound/ second_level.py effects/ echo.py formats/ wav_write.py {snippet} {your code}35 với một
python-sibling-import/ top_level.py sound/ second_level.py effects/ echo.py formats/ wav_write.py {snippet} {your code}36 thích hợp. Trong trường hợp này,
from sub1.helper import helper
from sub2.utils import some_func
7 có thể được cài đặt cục bộ dưới dạng gói. Vì vậy, nó không được áp dụng khi dự án không phải là một góiMột lựa chọn tốt hơn là di chuyển
$ python -m tests.test_sub1
7 vào một gói con mới, chẳng hạn như python-sibling-import/ top_level.py sound/ second_level.py effects/ echo.py formats/ wav_write.py {snippet} {your code}39, bao gồm
python-sibling-import/ top_level.py sound/ second_level.py effects/ echo.py formats/ wav_write.py {snippet} {your code}31 và
$ python -m tests.test_sub1
7. Sau đó, chúng tôi chuyển vấn đề này thành trường hợp nhập từ gói anh chị em, có giải pháp ở trên. Quan trọng hơn, tùy chọn này cũng hoạt động khi dự án gốc không phải là một góiTùy chọn cuối cùng là hack
python-sibling-import/ top_level.py sound/ second_level.py effects/ echo.py formats/ wav_write.py {snippet} {your code}52 nếu chúng tôi không muốn chuyển
$ python -m tests.test_sub1
7 sang gói con cũng như biến dự án thành một gói. Dựa trên bài đăng trên blog này và câu hỏi stackoverflow của Remi, chúng tôi có thể đặt mã bên dưới vào một tệp có tên là python-sibling-import/ top_level.py sound/ second_level.py effects/ echo.py formats/ wav_write.py {snippet} {your code}54
from sub1.helper import helper
from sub2.utils import some_func
1Sau đó, trong
python-sibling-import/ top_level.py sound/ second_level.py effects/ echo.py formats/ wav_write.py {snippet} {your code}30, trước tiên chúng tôi nhập nó sau đó nhập các mô-đun khác
from sub1.helper import helper
from sub2.utils import some_func
2Ghi chú. thuộc tính
python-sibling-import/ top_level.py sound/ second_level.py effects/ echo.py formats/ wav_write.py {snippet} {your code}56 không phải lúc nào cũng được cung cấp. Thay vì sử dụng
python-sibling-import/ top_level.py sound/ second_level.py effects/ echo.py formats/ wav_write.py {snippet} {your code}57, Remi đề xuất sử dụng mô-đun kiểm tra để truy xuất tên tệp [và đường dẫn] của tệp hiện tại. Sau khi hack
python-sibling-import/ top_level.py sound/ second_level.py effects/ echo.py formats/ wav_write.py {snippet} {your code}52, cả
python-sibling-import/ top_level.py sound/ second_level.py effects/ echo.py formats/ wav_write.py {snippet} {your code}59 và
python-sibling-import/ top_level.py sound/ second_level.py effects/ echo.py formats/ wav_write.py {snippet} {your code}70 đều hợp lệ