【问题标题】:How to embed python code in batch script如何在批处理脚本中嵌入python代码
【发布时间】:2013-07-02 06:59:17
【问题描述】:

在 bash 中,我们可以:

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

在 bash 脚本中嵌入 python 代码 sn-p。

但在 Windows 批处理中,这不起作用 - 虽然我仍然可以使用 python -c 但这需要我将代码合并为一行,这是我尽量避免的事情。

有没有办法在批处理脚本中实现这一点?

谢谢。

【问题讨论】:

  • 这与复制heredoc functionality in MS-DOS的更一般的问题有关。
  • @djf 目前尚不清楚该问题将如何解决我的问题 - 那是关于写入文件,我希望它被读入 python 解释器
  • Heredoc 可能是一种解决方案,但纯混合也可能是一种解决方案,因此它不是重复的
  • 您可以使用 more +1 %0 | 执行几乎 100% 相同的脚本python & exit /b 在第一行。肯定不是同一个问题。一些答案也一样!

标签: python windows bash batch-file


【解决方案1】:

摆脱必须立即在批处理文件中指定 python 脚本的想法。将 python 代码放在一个单独的文件中,然后在 python 下从 Windows 批处理文件启动单独的文件。

【讨论】:

  • 这是我尽量避免的——我想保持简洁,只提供 1 个脚本,而不是 2 个
  • 在某些情况下,只提供一个文件是可行的,而不会遇到很多麻烦。能够将两件事合二为一是一项非常有价值的功能。
【解决方案2】:

我知道的唯一方法是从批处理文件中调用 Python 脚本,如下所示:

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

【讨论】:

    【解决方案3】:

    您可以使用混合技术,此解决方案也适用于 python 导入。

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

    批处理代码位于多行字符串''' 中,因此对于 python 是不可见的。
    批处理解析器看不到 python 代码,因为它之前退出了。

    第一行是关键。
    它适用于批处理,也适用于 python!
    在 python 中,1&gt;2 只是一个没有输出的毫无意义的比较,该行的其余部分是 # 的注释。

    对于批处理 1&gt;2# 是将流 1 重定向到文件 2#
    command 是一个冒号 :,这表示一个标签,并且从不打印带标签的行。
    然后最后一个插入符号只是将下一行附加到标签行,因此批处理看不到 ''' 行。

    【讨论】:

    • 这是另一种解决方案,但如果它更好?这是一个见仁见智的问题。
    • 好吧,这是一个意见,但如果你把它放在第一行,它会更短:more +1 %~f0 | python & exit /b (或扩展 %0 以获得更好的结果)无论如何,它与提供的脚本更通用,它不需要依赖 python 特定的语法,因此它适用于任何相同的语言。
    • @lzprgmr %~f0 代表当前批处理文件的完整路径
    • “对于批次 1>2# 是将流 1 重定向到文件 2#。” - 这应该是一个空操作,其目的是注释掉下一行''',对吧?
    • 不,对于批处理,冒号是空操作,这删除1&gt;2#,以便批处理不会尝试打开文件2#跨度>
    【解决方案4】:

    效率更高,而且它将所有命令行参数传递给脚本并从脚本返回退出代码:

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

    以下是正在发生的事情的细分:

    • @ 阻止打印脚本行
    • SETLOCAL ENABLEDELAYEDEXPANSION 允许!ERRORLEVEL!待评估 python 脚本运行
    • &amp; 允许在同一行上运行另一个命令(类似于 UNIX 的 ;
    • python 运行 python 解释器(必须在 %PATH% 中)
    • -x 告诉 python 忽略第一行(运行 python -h 了解详情)
    • "%~f0" 扩展为当前正在执行的批处理脚本的完全限定路径(参数 %0)。如果路径包含空格,则会引用它
    • %* 扩展传递给脚本的所有参数,有效地将它们传递给 python 脚本
    • EXIT /B 告诉 Windows Batch 仅退出当前批处理文件(仅使用 EXIT 会导致调用解释器退出)
    • !ERRORLEVEL! 扩展为上一个命令运行后的返回码。用作EXIT /B 的参数,它会导致批处理脚本以从python 解释器收到的返回码退出

    注意:如果您的 python 二进制文件不在 PATH 中或位于非标准位置,您可能需要将“python”更改为其他内容。例如:

    @"C:\Path\To\Python.exe" -x ...
    

    【讨论】:

    • 不错!当您将第一行更改为 @python -x "%~f0" %* &amp; call set "EL=%%ErrorLevel%%" &amp; setlocal EnableDelayedExpansion &amp; exit /B !EL! 时,您可以避免脚本路径 (%~f0) 或包含 !-signs 的参数 (%*) 出现问题,否则会被延迟扩展消耗(假设它已关闭)默认)。不幸的是,@python -x "%~f0" %* &amp; call exit /B %ErrorLevel% 不起作用,因为它总是返回退出代码0(很可能是因为exitcall 成功)...
    【解决方案5】:
    @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
    

    可以包含任何字符或字符串,但只能包含“!”感叹是例外。 '!'用于变量,因此您必须设置“DisableDelayedExpansion”。最后,您必须设置“endlocal”。就是这样。

    您可以将此例程用于任何脚本或任何文档。即使 cmd 脚本...

    【讨论】:

      【解决方案6】:

      对于一个简单的命令:Windows cmd 提示符只能理解双引号,因此您可以将它们加倍以使用 -c 选项:

      python -c print("""Hi""")
      

      或使用 windows cmd 根本不解释的简单引号:

      python -c print('Hi')
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-07-30
        • 2011-11-01
        • 2011-06-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多