2010-04-08 38 views
42

Tôi có một tệp có tên foobar (không có phần mở rộng .py). Trong cùng một thư mục tôi có một tệp python khác cố gắng nhập nó:Nhập mô-đun python không có phần mở rộng .py

import foobar 

Nhưng điều này chỉ hoạt động nếu tôi đổi tên tệp thành foobar.py. Có thể nhập một mô-đun python không có phần mở rộng .py không?

Cập nhật: tệp không có phần mở rộng vì tôi cũng sử dụng nó làm tập lệnh độc lập và tôi không muốn nhập phần mở rộng .py để chạy.

Update2: Tôi sẽ đi cho giải pháp liên kết tượng trưng được đề cập bên dưới.

+1

Tôi tò mò. Tại sao bạn có một tệp python mà không có phần mở rộng 'py'? – voyager

+1

Đôi khi bạn nên sử dụng python cho các tệp cấu hình (phần mở rộng dưới dạng .conf) hoặc để biểu thị một loại tệp đặc biệt. Trong trường hợp của tôi, nó sẽ thuận tiện hơn cho một Quản trị viên. – NuclearPeon

+1

Tôi có tệp có cấu hình được sử dụng làm tệp python và dưới dạng tập lệnh bash. Tôi đã cho nó một phần mở rộng 'pysh' ... – osa

Trả lời

31

Bạn có thể sử dụng chức năng imp.load_source (từ mô-đun imp), để tải mô-đun động từ đường dẫn hệ thống tệp đã cho.

foobar = imp.load_source('foobar', '/path/to/foobar') 

Điều này SO discussion cũng hiển thị một số tùy chọn thú vị.

+0

Đã sửa lỗi. [đó là xây dựng hơn để đề xuất một chỉnh sửa, mặc dù] –

+0

nhưng một lần nữa phần là cần thiết như tôi hiểu từ >>> foobar = imp.load_source ('', 'thông tin xác thực') [mặc định] NameError: name 'default' không được xác định – Ilja

+2

Việc sử dụng đối số đầu tiên '' foobar'' nếu nó được gán trong giá trị trả về là gì? –

13

imp.load_source(module_name, path) nên làm hoặc bạn có thể làm imp.load_module(module_name, file_handle, ...) đường tiết hơn nếu bạn có một xử lý tập tin thay vì

13

Giống như những người khác đã đề cập, bạn có thể sử dụng imp.load_source, nhưng nó sẽ làm cho mã của bạn khó khăn hơn để đọc. Tôi thực sự sẽ chỉ giới thiệu nó nếu bạn cần phải nhập khẩu các mô-đun có tên hoặc đường dẫn không được biết đến cho đến khi thời gian chạy.

Lý do bạn không muốn sử dụng phần mở rộng .py là gì? Trường hợp phổ biến nhất cho việc không muốn sử dụng phần mở rộng .py, là bởi vì kịch bản lệnh python cũng chạy như một tệp thực thi, nhưng bạn vẫn muốn các mô-đun khác có thể nhập nó. Nếu đây là trường hợp, nó có thể có lợi để di chuyển chức năng vào một tập tin .py với một tên tương tự, và sau đó sử dụng foobar như một wrapper.

+12

Hoặc thay vì gói, chỉ cần symlink foobar.py để foobar (giả sử bạn không có trên Windows) – whaley

+0

@whaley, yeah, điều đó sẽ sạch hơn nhiều. Bạn có thể sử dụng một .bat cho các cửa sổ để thực hiện cùng một điều. –

+0

Tôi đã có một trường hợp sử dụng gọn gàng - một tệp readme, với các ví dụ trong đó, tôi muốn doctest xác thực. Tôi hy vọng sẽ tạo ra một tài liệu doctest markdown hoạt động ... –

1

Nếu bạn cài đặt kịch bản với người quản lý gói (deb hoặc tương tự) tùy chọn khác sẽ được sử dụng setuptools:

"...there’s no easy way to have a script’s filename match local conventions on both Windows and POSIX platforms. For another, you often have to create a separate file just for the “main” script, when your actual “main” is a function in a module somewhere... setuptools fixes all of these problems by automatically generating scripts for you with the correct extension, and on Windows it will even create an .exe file..."

https://pythonhosted.org/setuptools/setuptools.html#automatic-script-creation

4

Đây là một giải pháp cho Python 3.4 trở lên:

from importlib.util import spec_from_loader, module_from_spec 
from importlib.machinery import SourceFileLoader 

spec = spec_from_loader("foobar", SourceFileLoader("foobar", "/path/to/foobar")) 
foobar = module_from_spec(spec) 
spec.loader.exec_module(foobar) 

Sử dụng spec_from_loader và chỉ định rõ ràng SourceFileLoader sẽ bắt buộc machinery để tải tệp s, mà không cố gắng tìm ra loại tệp từ phần mở rộng. Điều này có nghĩa là bạn có thể tải tệp ngay cả khi nó không được liệt kê trong importlib.machinery.SOURCE_SUFFIXES.

Nếu bạn muốn giữ lại nhập khẩu các tập tin có tên sau khi tải đầu tiên, thêm module để sys.modules:

sys.modules['foobar'] = foobar 
Các vấn đề liên quan