Có gì sai với nhập khẩu tương đối trong Python?


89

Gần đây tôi đã nâng cấp các phiên bản của pylint , một trình kiểm tra kiểu Python phổ biến.

Nó đã đi theo hướng đạn đạo trong suốt mã của tôi, chỉ ra những nơi tôi nhập các mô-đun trong cùng một gói, mà không chỉ định đường dẫn gói đầy đủ.

Thông báo lỗi mới là W0403.

W0403: Nhập khẩu tương đối% r, nên là% r

Được sử dụng khi nhập khẩu liên quan đến thư mục gói được phát hiện.


Thí dụ

Ví dụ: nếu các gói của tôi có cấu trúc như thế này:

/cake
  /__init__.py
  /icing.py
  /sponge.py
/drink

và trong gói bọt biển tôi viết:

import icing

thay vì

import cake.icing

Tôi sẽ nhận được lỗi này.


Mặc dù tôi hiểu rằng không phải tất cả các thông điệp của Pylint đều có tầm quan trọng như nhau và tôi không ngại loại bỏ chúng, tôi không hiểu tại sao thực hành như vậy lại bị coi là một ý tưởng tồi.

Tôi đã hy vọng ai đó có thể giải thích những cạm bẫy, vì vậy tôi có thể cải thiện phong cách mã hóa của mình hơn là (như tôi hiện đang dự định làm) tắt cảnh báo rõ ràng giả mạo này.

Câu trả lời:


97

Vấn đề import icinglà bạn không biết đó là nhập tuyệt đối hay nhập tương đối. icingcó thể một mô-đun trong đường dẫn của python hoặc một gói trong mô-đun hiện tại. Điều này khá khó chịu khi một gói cục bộ có cùng tên với gói thư viện chuẩn python.

Bạn có thể làm điều from __future__ import absolute_importđó tắt hoàn toàn nhập khẩu tương đối. Nó được mô tả, bao gồm cả bằng chứng này về sự không rõ ràng, trong PEP 328 . Tôi tin rằng Python 3000 đã hoàn toàn nhập khẩu tương đối tắt.

Bạn vẫn có thể thực hiện nhập khẩu tương đối, nhưng bạn phải thực hiện chúng một cách rõ ràng, như thế này:

from . import icing

2
+1 đặc biệt là cho giải pháp thỏa hiệp, đó có lẽ là con đường tôi nên đi.
Oddthinking ngày

2
Lưu ý bạn cũng có thể làm import .icingthay vìfrom . import icing
Jack

11
@Jack thực sự tôi không nghĩ bạn có thể. Từ phần này của PEP328 : Nhập khẩu tương đối phải luôn luôn sử dụng from <> import; import <>luôn luôn là tuyệt đối Tất nhiên, nhập khẩu tuyệt đối có thể sử dụng from <> importbằng cách bỏ qua các dấu chấm hàng đầu. Lý do import .foobị cấm là vì sau import XXX.YYY.ZZZđó XXX.YYY.ZZZcó thể sử dụng được trong một biểu thức. Nhưng .moduleYkhông thể sử dụng trong một biểu thức.
A.Wan

48

Có một vài lý do tốt:

  1. Nhập khẩu tương đối dễ dàng phá vỡ, khi bạn di chuyển một mô-đun xung quanh.

    Hãy tưởng tượng bạn có một foo.bar, một foo.bazvà một bazmô-đun trong gói của bạn. foo.barnhập khẩu foo.baz, nhưng sử dụng nhập khẩu tương đối.

    Bây giờ, nếu bạn đã chuyển foo.barđến bar, mô-đun của bạn đột nhiên nhập một khác baz!

  2. Nhập khẩu tương đối là mơ hồ. Ngay cả khi không di chuyển xung quanh barmô-đun trong ví dụ trên, một nhà phát triển mới đến dự án của bạn có thể được tha thứ vì không nhận ra đó bazthực sự là foo.bazthay vì bazgói cấp gốc .

    Nhập khẩu tuyệt đối làm cho nó rõ ràng những gì mô-đun đang được sử dụng. Và như lời import thisrao giảng, rõ ràng là tốt hơn là ngầm.

  3. Python 3 đã vô hiệu hóa hoàn toàn nhập khẩu tương đối; nhập khẩu bây giờ luôn được hiểu là tuyệt đối, có nghĩa là trong ví dụ trên import bazsẽ luôn nhập mô-đun cấp cao nhất. Bạn sẽ phải sử dụng cú pháp nhập rõ ràng thay thế ( from . import baz).

    Do đó, việc chuyển ví dụ từ Python 2 sang 3 sẽ dẫn đến các sự cố không mong muốn, sử dụng nhập tuyệt đối ngay bây giờ sẽ giúp mã của bạn trở thành bằng chứng trong tương lai.


10
+1 cho # 2 và # 3. Nhưng # 1 phải được bù đắp cho những gì xảy ra khi toàn bộ thư mục được di chuyển (ví dụ: đẩy xuống một mức).
Oddthinking ngày
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.