2013-07-04 12 views
6

Trong bash, chúng ta có thể:Làm thế nào để nhúng mã python trong tập lệnh batch

python - << EOF 
import os 
print 'hello' 
EOF 

để nhúng đoạn mã python trong kịch bản bash. Tuy nhiên, trong lô Windows, điều này không hoạt động - mặc dù tôi vẫn có thể sử dụng python -c nhưng điều đó đòi hỏi tôi phải gom mã của tôi thành một dòng, đó là điều tôi cố gắng tránh.

Có cách nào để đạt được điều này trong tập lệnh theo lô không?

Cảm ơn.

+1

Điều này liên quan đến câu hỏi tổng quát hơn về sao chép [chức năng heredoc trong MS-DOS] (http://stackoverflow.com/questions/1015163/heredoc-for-windows-batch). –

+0

@djf không rõ câu hỏi đó giải quyết vấn đề của tôi như thế nào - đó là viết vào một tập tin, tôi muốn nó được đọc vào trong python intepreter –

+0

Heredoc _could_ là một giải pháp, nhưng lai thuần túy cũng có thể là một giải pháp nó không phải là một bản sao – jeb

Trả lời

10

Bạn có thể sử dụng một kỹ thuật lai.

1>2# :^
''' 
@echo off 
echo normal 
echo batch code 
echo Switch to python 
python "%~f0" 
exit /b 
rem^
''' 
print "This is Python code" 

Mã lô là một chuỗi nhiều dòng ''' vì vậy điều này là vô hình đối với python.
Trình phân tích cú pháp theo lô không thấy mã python, khi nó thoát ra trước đó.

Dòng đầu tiên là khóa.
Nó có giá trị cho hàng loạt cũng như cho python!
Trong python nó chỉ là một sự vô nghĩa so sánh 1>2 mà không có đầu ra, phần còn lại của dòng là một bình luận của #.

Đối với hàng loạt 1>2# là chuyển hướng luồng 1 vào tệp 2#.
Lệnh là dấu hai chấm : điều này cho biết nhãn và các dòng được gắn nhãn không bao giờ được in.
Sau đó, dấu sót cuối cùng chỉ cần nối thêm dòng tiếp theo vào dòng nhãn, do đó lô không thấy dòng '''.

+0

Đó là một giải pháp khác, nhưng nếu nó đẹp hơn? Đó là vấn đề của ý kiến. – jeb

+0

cũng có ý kiến ​​đó nhưng ngắn hơn nếu bạn đặt dòng này lên dòng đầu tiên: ** +1% ~ f0 | python & exit/b ** (hoặc mở rộng% 0 để có kết quả tốt hơn) Dù sao nó cũng giống như kịch bản được cung cấp và nó không cần phải dựa vào cú pháp cụ thể của python để nó hoạt động với bất kỳ ngôn ngữ nào giống nhau. – joojaa

+0

tất cả những điều này xảy ra như một phép thuật ... –

1

Tự rút mình khỏi ý tưởng rằng bạn phải ngay lập tức chỉ định tập lệnh python trong tệp lô. Đặt mã python trong một tệp riêng biệt và sau đó chỉ cần khởi chạy tệp riêng biệt dưới python từ tệp lô Windows.

+0

đây là điều tôi cố gắng tránh - Tôi muốn giữ ngắn gọn bằng cách chỉ phân phối 1 tập lệnh, không phải 2 –

+0

Có những trường hợp chắc chắn khi nó chỉ khả thi để cung cấp một tệp duy nhất mà không gặp nhiều rắc rối. Việc có thể kết hợp hai thứ thành một là một tính năng khá có giá trị. – mojo

0

Cách duy nhất tôi biết để làm điều này là để gọi script Python từ tập tin thực thi như thế này:

@echo off 
REM whatever other code 
python python_script.py 
REM rest of batch file... 
13

Thậm chí hiệu quả hơn, cộng với nó vượt qua tất cả đối số dòng lệnh để và trả về mã thoát khỏi kịch bản:

@SETLOCAL ENABLEDELAYEDEXPANSION & python -x "%~f0" %* & EXIT /B !ERRORLEVEL! 
# Your python code goes here... 

Đây là một sự thất bại của những gì đang xảy ra:

  • @ ngăn chặn dòng tập lệnh được in
  • SETLOCAL ENABLEDELAYEDEXPANSION cho phép! ERRORLEVEL!được đánh giá sau kịch bản python chạy
  • & cho phép lệnh khác để được chạy trên cùng một dòng (tương tự như ; UNIX của)
  • python chạy thông dịch viên python (Phải ở% PATH%)
  • -x yêu cầu python bỏ qua dòng đầu tiên (Chạy python -h để biết chi tiết)
  • "%~f0" mở rộng đến đường dẫn đầy đủ điều kiện của tập lệnh thực thi hiện tại (Đối số% 0). Nó được trích dẫn trong trường hợp các đường dẫn chứa không gian
  • %* mở rộng tất cả các đối số được truyền đến kịch bản, một cách hiệu quả thông qua họ vào kịch bản python
  • EXIT /B nói cho Windows hàng loạt để thoát khỏi tập tin thực thi hiện tại chỉ (Sử dụng chỉ EXIT sẽ gây ra gọi thông dịch viên để thoát)
  • !ERRORLEVEL! mở rộng đến mã trả về từ lệnh trước đó sau khi nó được chạy. Được sử dụng làm đối số cho EXIT /B, nó làm cho tập lệnh batch được thoát ra với mã trả về nhận được từ trình thông dịch python

LƯU Ý: Bạn có thể phải thay đổi "python" thành thứ khác nếu nhị phân python của bạn không có trong PATH hoặc ở vị trí không chuẩn. Ví dụ: '!'

@"C:\Path\To\Python.exe" -x ... 
0
@echo off 
setlocal EnableDelayedExpansion 

set "fTmpPy=%TEMP%\~fTmp.py" 

call :getLine "::python_beg" "::python_end" > "!fTmpPy!" 

python "!fTmpPy!" 

pause 
exit /b 0 

:getLine <beg str> <end str> 
    set "bBegEnd=0" 
    for /f "usebackq delims=" %%l in ("%~f0") do (
    if !bBegEnd! equ 1 (
     if "%%l" equ "%~2" (exit /b 0) 
     setlocal DisableDelayedExpansion 
     echo %%l 
     endlocal 
    ) else (
     if "%%l" equ "%~1" (set "bBegEnd=1") 
    ) 
) 
exit /b 0 

endlocal 

::mark is unique - one character or string 
::begin mark must be 
::end mark is optional if it is on eof 

::python_beg 
print('Hello, world!') 
::python_end 

Có thể trong đó có bất kỳ ký tự hoặc chuỗi, nhưng điều duy nhất dấu chấm than là ngoại lệ. '!' được sử dụng cho biến, vì vậy bạn phải đặt 'DisableDelayedExpansion'. Cuối cùng, bạn phải đặt 'endlocal'. Đó là tất cả.

Bạn có thể sử dụng thường trình này cho bất kỳ tập lệnh hoặc tài liệu nào. Mặc dù tập lệnh cmd ...