Tôi có thể sử dụng __init__.py để xác định các biến toàn cục không?


130

Tôi muốn xác định một hằng số nên có sẵn trong tất cả các mô hình con của gói. Tôi đã nghĩ rằng nơi tốt nhất sẽ nằm trong __init__.pytệp của gói gốc. Nhưng tôi không biết làm thế nào để làm điều này. Giả sử tôi có một vài gói con và mỗi gói có một vài mô-đun. Làm thế nào tôi có thể truy cập biến đó từ các mô-đun?

Tất nhiên, nếu điều này là hoàn toàn sai, và có một sự thay thế tốt hơn, tôi muốn biết điều đó.

Câu trả lời:


196

Bạn sẽ có thể đặt chúng vào __init__.py. Điều này được thực hiện tất cả các thời gian.

mypackage/__init__.py:

MY_CONSTANT = 42

mypackage/mymodule.py:

from mypackage import MY_CONSTANT
print "my constant is", MY_CONSTANT

Sau đó, nhập khẩu mô-đun:

>>> from mypackage import mymodule
my constant is 42

Tuy nhiên, nếu bạn có các hằng số, sẽ rất hợp lý (có thể là thực tiễn tốt nhất) để đặt chúng vào một mô-đun riêng (constants.py, config.py, ...) và sau đó nếu bạn muốn chúng trong không gian tên gói, hãy nhập họ

mypackage/__init__.py:

from mypackage.constants import *

Tuy nhiên, điều này không tự động bao gồm các hằng số trong không gian tên của các mô-đun gói. Mỗi mô-đun trong gói sẽ vẫn phải nhập các hằng rõ ràng từ mypackagehoặc từ mypackage.constants.


19
Đây phải là câu trả lời được chấp nhận. Nếu bạn đang làm việc với Python 2.5 trở lên, bạn cũng có thể sử dụng nhập tương đối rõ ràng cũng như được mô tả ở đây : from . import MY_CONSTANT
ThatAintWorking

không cách thứ hai chỉ làm việc cho hằng số? from mypackage.constants import *sẽ đặt các bản sao của MY_CONSTANTmỗi mô hình con thay vì tham chiếu đến cùng một biến
hardmooth 18/03/2016

@hardmooth: Không chính xác. Các giá trị được sao chép bằng tham chiếu, vì vậy nếu bạn biến đổi MY_CONSTANTtrong bất kỳ mô-đun nào, nó sẽ biến đổi ở mọi nơi. Nếu bạn chỉ định lại MY_CONSTANTtrong bất kỳ mô-đun nào, nó sẽ chỉ ảnh hưởng đến mô-đun đó. Nếu đó là ý định của bạn, bạn phải tham chiếu theo thuộc tính, nghĩa là mypackage.constants.MY_CONSTANT.
Jason R. Coombs

7
Một đánh bắt với ví dụ là nếu bạn nhập mymodule.pyvào __init__.pytrước MY_CONSTANT = 42đó sẽ thất bại bởi vì khi nhập khẩu mymodule.py MY_CONSTANTchưa được xác định được nêu ra. Vì vậy, cần phải di chuyển MY_CONSTANT = 42ở trênimport mymodule
markmnl

Làm thế nào là về biến? Đó là hỏi về các biến, không phải hằng. Làm thế nào python xử lý biến trong gói? Điều gì nếu biến trong gói đã được thay đổi?
TomSawyer

31

Bạn không thể làm điều đó. Bạn sẽ phải nhập rõ ràng các hằng số của mình vào không gian tên của từng mô-đun riêng lẻ. Cách tốt nhất để đạt được điều này là xác định các hằng số của bạn trong mô-đun "config" và nhập nó ở mọi nơi bạn yêu cầu:

# mypackage/config.py
MY_CONST = 17

# mypackage/main.py
from mypackage.config import *

Vâng, một tập tin cấu hình là những gì tôi muốn. Tôi chỉ nghĩ rằng init .py sẽ là một nơi tốt. Giải pháp của bạn nghe có vẻ như thực hành tiêu chuẩn. Là nó?
Andrei Vajna II

1
Điểm tốt. Tôi không nhận ra câu hỏi là để các hằng số tự động được đặt trong không gian tên của tất cả các mô-đun gói.
Jason R. Coombs

Nhưng mỗi khi tập lệnh nhập config.txt, mã bên trong sẽ được thực thi. Bạn có đề xuất gì nếu mã bên trong config.py chỉ được chạy một lần? Giả sử tôi đang đọc tệp settings.json bên trong config.py và tôi không muốn mở () mỗi lần tôi nhập config.py.
Augiwan

@UGS Đây không phải là cách Python hoạt động. Mỗi mô-đun chỉ được thực hiện một lần. Khi được nhập lần thứ hai, mô-đun đã được lưu vào bộ đệm sys.modules.
Ferdinand Beyer

@FerdinandBeyer Rất tiếc! Tôi quên đề cập rằng tôi đang nhập config.py từ một số tập lệnh chứ không phải cùng một tập lệnh. Giả sử a.txt đang nhập config.py & b.py và b.py đang nhập config.py. Tôi đã tự hỏi nếu có thể đảm bảo mã bên trong config.py chỉ được thực thi một lần.
Augiwan

2

Bạn có thể định nghĩa các biến toàn cầu từ bất cứ đâu, nhưng đó là một ý tưởng thực sự tồi tệ. nhập __builtin__mô-đun và sửa đổi hoặc thêm thuộc tính cho mô-đun này và đột nhiên bạn có các hằng số hoặc hàm dựng sẵn mới. Trong thực tế, khi ứng dụng của tôi cài đặt gettext, tôi nhận được hàm _ () trong tất cả các mô-đun của mình mà không cần nhập bất cứ thứ gì. Vì vậy, điều này là có thể, nhưng tất nhiên chỉ dành cho các dự án loại Ứng dụng, không dành cho các gói hoặc mô-đun có thể tái sử dụng.

Và tôi đoán không ai muốn giới thiệu thực hành này anyway. Có gì sai với một không gian tên? Ứng dụng cho biết có mô-đun phiên bản, do đó tôi có sẵn các biến "toàn cầu" version.VERSION, version.PACKAGE_NAMEv.v.


0

Chỉ muốn thêm rằng các hằng số có thể được sử dụng bằng tệp config.ini và được phân tích cú pháp trong tập lệnh bằng thư viện configparser. Bằng cách này bạn có thể có hằng số cho nhiều trường hợp. Chẳng hạn, nếu bạn có các hằng số tham số cho hai yêu cầu url riêng biệt, chỉ cần gắn nhãn chúng như vậy:

mymodule/config.ini
[request0]
conn = 'admin@localhost'
pass = 'admin'
...

[request1]
conn = 'barney@localhost'
pass = 'dinosaur'
...

Tôi thấy tài liệu trên trang web Python rất hữu ích. Tôi không chắc có sự khác biệt nào giữa Python 2 và 3 hay không, vì vậy đây là các liên kết đến cả hai:

Đối với Python 3: https://docs.python.org/3/l Library / configparser.html # model-configparser

Đối với Python 2: https://docs.python.org/2/l Library / configparser.html # model-configparser

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.