2011-05-29 25 views
9

Tôi có một mô-đun C thuần túy cho Python và tôi muốn có thể gọi nó bằng cách sử dụng phương pháp python -m modulename. Điều này làm việc tốt với các mô đun được triển khai trong Python và một cách giải quyết rõ ràng là thêm một tệp phụ cho mục đích đó. Tuy nhiên, tôi thực sự muốn giữ mọi thứ cho một nhị phân phân phối duy nhất của tôi và không thêm tệp thứ hai chỉ cho cách giải quyết này.Bắt mô-đun python để làm việc cho một mô-đun được triển khai trong C

Tôi không quan tâm đến cách thức giải pháp của hacky.

Nếu bạn cố gắng sử dụng mô-đun C với -m thì bạn nhận được thông báo lỗi No code object available for <modulename>.

+0

Bạn sử dụng công cụ gì, bạn đang cố gắng đạt được điều gì, nền tảng là gì? Bạn sử dụng bao nhiêu thư viện chuẩn? Là mô-đun của bạn và nguồn đóng, hoặc một cái gì đó chúng ta có thể nhìn vào? Tôi không thể giúp đỡ mà không có một số thông tin. – janislaw

+0

Cảm ơn sự nhiệt tình nhưng vấn đề còn sâu sắc hơn so với câu hỏi của bạn. Module này được viết bằng C bằng cách sử dụng các phương thức Python chuẩn để thực hiện điều đó. Bắt đầu tại trang này để có được một ý tưởng: http://docs.python.org/extending/extending.html "Công cụ" là cơ chế Python chuẩn cho các phần mở rộng C, những gì tôi đang cố gắng đạt được là trong mô tả, tất cả các nền tảng, thư viện chuẩn không liên quan (mã trong C không Python), mô-đun là của tôi và nguồn mở và đủ phức tạp mà tôi khuyên bạn nên sử dụng mô-đun ví dụ từ trang tài liệu python. –

+0

Bạn đã bao giờ sản xuất tệp thực thi được cố định trong Python chưa? Tùy thuộc vào nền tảng, nó bó với tất cả các mã thực thi nó cần để chạy. Tôi đã từng chuyển một chương trình python sang linux, và phải gửi libglib và libz cùng với tệp thực thi được đông lạnh. Trên Windows, OTOH có msvcrtxx.dll mà bạn có thể cần gửi. Thậm chí nếu bạn viết chương trình C với Python.lib được liên kết tĩnh, bạn cần phải đính kèm các thư viện động, để đánh bại mục đích tập tin đơn lẻ. – janislaw

Trả lời

2

-m triển khai ở runpy._run_module_as_main. Bản chất của nó là:

mod_name, loader, code, fname = _get_module_details(mod_name) 
<...> 
exec code in run_globals 

Mô-đun được biên dịch không có "đối tượng mã" được liên kết với nó sao cho câu lệnh 1 không thành công với ImportError("No code object available for <module>"). Bạn cần phải mở rộng runpy - cụ thể, _get_module_details - để làm cho nó hoạt động cho một mô-đun được biên dịch. Tôi đề nghị trả lại một đối tượng đang được xây dựng từ nói trên "import mod; mod.main()": (python 2.6.1)

code = loader.get_code(mod_name) 
    if code is None: 
+  if loader.etc[2]==imp.C_EXTENSION: 
+   code=compile("import %(mod)s; %(mod)s.main()"%{'mod':mod_name},"<extension loader wrapper>","exec") 
+  else: 
+   raise ImportError("No code object available for %s" % mod_name) 
-  raise ImportError("No code object available for %s" % mod_name) 
    filename = _get_filename(loader, mod_name) 

(Cập nhật: cố định một lỗi trong chuỗi định dạng)

Bây giờ ...

C:\Documents and Settings\Пользователь>python -m pythoncom 

C:\Documents and Settings\Пользователь> 

Điều này vẫn không hoạt động đối với các mô đun dựng sẵn. Một lần nữa, bạn sẽ cần phải phát minh ra một số khái niệm về "đơn vị mã chính" cho chúng.

Cập nhật:

Tôi đã nhìn qua internals gọi từ _get_module_details và có thể nói với sự tự tin rằng họ thậm chí không nỗ lực để lấy một đối tượng mã từ một mô-đun kiểu khác hơn imp.PY_SOURCE, imp.PY_COMPILED hoặc imp.PKG_DIRECTORY. Vì vậy, bạn để vá máy móc này theo cách này hoặc cách khác để -m hoạt động. Python bị lỗi trước khi truy xuất bất kỳ thứ gì từ mô-đun của bạn (nó thậm chí không kiểm tra xem tệp dll có phải là mô-đun hợp lệ) hay không. Vì vậy, bạn không thể làm bất cứ điều gì bằng cách tạo nó theo cách đặc biệt.

+0

Cảm ơn câu trả lời chi tiết. Tôi đã hy vọng tôi có thể kéo một số diễn viên đóng thế trong mã C của tôi trả về mô-đun gắn một đối tượng mã ở đó. –

+0

Từ quản lý POV, một kịch bản trình bao bọc trông là giải pháp tốt nhất cho tôi. Thật dễ dàng để đặt tên và đặt nó để nó được gọi thay vì python.exe bất cứ khi nào người dùng gọi "python". –

+0

Vấn đề với bất kỳ điều gì khác ngoài 'python -m module 'là tôi phải phân phối nhiều hơn một tệp, và sau đó người dùng phải tìm ra nơi để đặt tệp thứ hai đó và có thể thực thi nó. Xem xét các quyền khác nhau (người dùng so với quản trị viên), các nền tảng khác nhau, sự phân biệt giữa các nhà phát triển và người dùng cho mô-đun của tôi vv. Thật đáng tiếc là Python không cho phép -m làm việc với các phần mở rộng của C và thậm chí không có một hack kinh tởm sẽ làm các trick. –

-1

Tôi nghĩ rằng bạn cần bắt đầu bằng cách tạo một tệp riêng biệt bằng Python và nhận tùy chọn -m làm việc. Sau đó, biến tệp Python đó thành đối tượng mã và kết hợp nó vào nhị phân của bạn theo cách mà nó tiếp tục hoạt động.

Tra cứu các công cụ thiết lập trong PyPi, tải xuống .egg và xem tập tin. Bạn sẽ thấy rằng một vài byte đầu tiên chứa một kịch bản Python và chúng được theo sau bởi một tệp .ZIP bytestream. Một cái gì đó tương tự có thể làm việc cho bạn.

+1

Bắt Python bytecode là tầm thường - Py_CompileString sẽ nhận được điều đó. Tuy nhiên tôi không thấy cách nào để gắn mã byte vào PyObject được trả về từ Py_InitModule3/PyModule_Create. –

-1

Có một điều hoàn toàn mới có thể giải quyết vấn đề của bạn dễ dàng. Tôi vừa mới biết về nó và nó có vẻ đẹp đẽ đối với tôi: http://code.google.com/p/pts-mini-gpl/wiki/StaticPython

+1

Không áp dụng từ xa. Tôi muốn mô-đun của tôi hoạt động với Python đã cài đặt hiện tại không có mô-đun được tạo riêng. –

0

Yêu cầu của bạn về nhị phân phân phối cho phép sử dụng trứng? Nếu vậy, bạn có thể đóng gói module của bạn với một __main__.py với mã gọi của bạn và thường __init__.py ...

Nếu bạn thực sự kiên quyết, có lẽ bạn có thể mở rộng pkgutil.ImpLoader.get_code trở về một cái gì đó cho module C (ví dụ, có thể chức năng đặc biệt __code__). Để làm điều đó, tôi nghĩ bạn sẽ phải thay đổi nó trong nguồn Python. Ngay cả khi đó, pkgutil sử dụng exec để thực thi khối mã, vì vậy nó sẽ phải là mã Python.

TL; DR: Tôi nghĩ bạn đã bị euchred. Trong khi các mô-đun Python có mã ở mức toàn cục chạy ở thời gian nhập, các mô-đun C không; chúng chủ yếu chỉ là một không gian tên dict. Vì vậy, chạy một mô-đun C không thực sự có ý nghĩa từ quan điểm khái niệm. Bạn cần một số mã Python thực để chỉ đạo hành động.

+0

Tôi không tin rằng trứng hỗ trợ biên dịch mã. Tôi chỉ có thể mở rộng pkgutil trong khi mô-đun của tôi đang tải vì đó là mã đầu tiên chạy, nhưng nó sẽ là quá muộn. Nó thực sự khó chịu rằng hiện tại giải pháp là 'python -c" mô-đun nhập khẩu; module.main() "'hoặc có tệp .py chỉ với 4 từ đó. –

Các vấn đề liên quan