Mặc dù câu hỏi này đã được hỏi và trả lời nhiều lần (ví dụ, ở đây , ở đây , ở đây và ở đây ) theo ý kiến của tôi câu trả lời không hiện đầy đủ hoặc chính xác chụp tất cả những tác động của -m
cờ. Do đó, những điều sau đây sẽ cố gắng cải thiện những gì đã đến trước đó.
TLD
Các -m
lệnh thực hiện rất nhiều thứ không phải tất cả trong số họ hẳn sẽ cần tất cả các thời gian. Nói tóm lại: (1) cho phép các tập lệnh python được thực thi thông qua tên modul thay vì tên tệp (2) cho phép một người chọn một thư mục để thêm vào sys.path
để import
giải quyết và (3) cho phép các tập lệnh python có nhập tương đối hoạt động giống như khi chúng gọi qua import
.
Sơ bộ
Để hiểu tầm quan trọng của -m
cờ, cần phải làm rõ một thuật ngữ nhỏ.
Đầu tiên, các tệp mà Python có thể thực thi được gọi là các mô-đun. Thông thường các mô-đun chúng tôi quan tâm là *.py
các tệp, nhưng không phải luôn luôn. Ví dụ, có thể viết các mô-đun Python bằng C để thực hiện mã quan trọng. Sự phân biệt này sẽ trở nên quan trọng sau này. Cho đến nay, đủ để biết rằng các mô-đun không phải là gói là các tệp.
Thứ hai, Python xác định các mô-đun thông qua một <modulename>
định danh duy nhất (ví dụ import <modulename>
:). Đối với mỗi duy nhất <modulename>
cũng có một tệp duy nhất ở đâu đó trên máy với sự độc đáo của riêng nó <filename>
. Các trình thông dịch Python tuân theo một số quy tắc được xác định rõ ràng được xây dựng xung quanh sys.path
để ánh xạ <modulename>
tới a <filename>
(để biết thêm về cách thực hiện điều này, xem PEP 302 ).
Lịch sử phát triển của -m
Với ý nghĩa sơ bộ -m
có thể được giải thích theo nghĩa đơn giản nhất là bảo python tìm một mô-đun để thực hiện thông qua <modulename>
chứ không phải <filename>
. Nghĩa là, được đưa ra một <filename>
hoặc <modulename>
cho cùng một mô-đun, hai lệnh sau là tương đương python <filename>
hoặc python -m <modulename>
.
Trong bản phát hành 2.4.1 ban đầu , nơi -m
đã được thêm vào, tất cả những gì nó đã làm là tìm và thực thi các mô-đun bằng cách <modulename>
(cùng với việc thêm thư mục hiện tại vào sys.path
để có thể tìm thấy các mô đun cục bộ). Theo PEP 338, việc triển khai ban đầu cũng bị hạn chế do đó -m
không thể tham chiếu tên mô-đun trong các gói (nghĩa là phiên bản 2.4.1 sẽ không hỗ trợ tên mô-đun http.server
nhưng sẽ hỗ trợ timeit
).
Với việc bổ sung PEP 338 , -m
chức năng đã được mở rộng để hỗ trợ các <modulename>
đại diện trong các gói. Điều này có nghĩa là những cái tên như http.server
bây giờ đã được hỗ trợ đầy đủ -m
. Tăng cường này cũng có nghĩa là tất cả các gói trong một tên mô-đun đã được nạp (ví dụ, gói __init__.py
file đã được thực hiện), cùng với các mô-đun riêng của mình, trong trường hợp các gói sửa đổi của họ __path__
trong __init__.py
.
Một trường hợp sử dụng đáng chú ý được hỗ trợ -m
sau PEP 338 là các câu lệnh nhập tuyệt đối trong các gói tùy chỉnh mà không cần phải cài đặt gói sys.path
. Điều này có thể đạt được bằng cách sử dụng đơn giản -m
để tải các tệp script từ thư mục gốc của dự án tùy chỉnh (vì thư mục gốc sau đó sẽ được thêm vào sys.path
).
Cải tiến tính năng chính cuối cùng -m
đã đi kèm với PEP 366 . Với bản cập nhật này -m
đã đạt được khả năng hỗ trợ không chỉ nhập tuyệt đối mà cả nhập khẩu tương đối rõ ràng. Điều này đã đạt được bằng cách sửa đổi __package__
biến cho mô-đun được đặt tên trong -m
lệnh.
Với tất cả các cải tiến trên được thực hiện cho -m
nó vẫn còn một thiếu sót lớn. Nó chỉ có thể thực thi các mô-đun được viết bằng python (tức là *.py
). Nếu một tên mô-đun đề cập đến một mô-đun biên dịch C được chuyển đến -m
lỗi sau đây được tạo ra No code object available for <modulename>
.
So sánh -m
với các phương pháp thực hiện khác
Trái tim, -m
cờ là một phương tiện để thực thi các tập lệnh python thông qua tên modul chứ không phải tên tệp. Vì lý do này, chúng tôi so sánh nó với hai phương thức nổi tiếng khác để thực hiện các mô-đun: (1) tên tệp với python
lệnh và (2) tên mô-đun với import
câu lệnh.
Tác dụng của việc thực thi tên tệp bằng python
lệnh (tức là python <filename>
):
- Python's
sys.path
được sửa đổi để bao gồm vị trí của mô-đun trong độ phân giải nhập
- Biến của mô-đun
__name__
được đặt thành'__main__'
- Biến của mô-đun
__package__
được đặt thànhNone
- Không có
__init__.py
tệp nào sẽ được thực thi cho các gói cha trong<filename>
Hiệu ứng của việc thực thi modulename với import
câu lệnh (tức là import <modulename>
):
- Python
sys.path
là không sửa đổi trong bất kỳ cách nào để giải quyết nhập khẩu
- Biến của mô-đun
__name__
được đặt thành tên mô-đun tuyệt đối của nó
- Biến của mô-đun
__package__
được đặt thành gói chứa trong<modulename>
- Tất cả
__init__.py
các tệp sẽ được thực thi cho các gói cha mẹ trong<modulename>
Hiệu ứng của việc thực thi modulename với -m
cờ (tức là python -m <modulename>
):
- Python's
sys.path
được sửa đổi để bao gồm thư mục hiện tại trong độ phân giải nhập
- Biến của mô-đun
__name__
được đặt thành'__main__'
- Biến của mô-đun
__package__
được đặt thành gói chứa trong<modulename>
- Tất cả
__init__.py
các tệp sẽ được thực thi cho các gói cha mẹ trong<modulename>
Tóm lược
Các -m
lá cờ chỉ đơn giản là một cách khác để thực hiện một kịch bản python qua môđun chứ không phải là tên tập tin. Vì lý do này, người ta cần có ít nhất một sự hiểu biết nhỏ về cách Python ánh xạ các modulename thành tên tệp để tận dụng tối đa lợi thế của nó. Với cách hiểu này mặc dù người ta có được một công cụ mới mạnh mẽ kết hợp các tính năng của import
câu lệnh (ví dụ: hỗ trợ cho câu lệnh nhập tương đối rõ ràng) với sự tiện lợi của câu lệnh dòng python
lệnh.
-m
dường như tìm kiếmmymod1
trong đường dẫn thư viện mặc định. Ví dụ:python -m SimpleHTTPServer
hoạt động, trong khipython SimpleHTTPServer
thất bại vớican't open file 'SimpleHTTPServer': [Errno 2] No such file or directory
.