[英]running a bat file though python in current process
我正在尝试通过python脚本构建大型系统。 我首先需要为Visual Studio设置环境。 遇到问题后,我决定看看是否可以设置并启动Visual Studio。 我首先设置了几个环境变量,然后调用C:\\Program Files (x86)\\Microsoft Visual Studio 11.0\\VC\\vcvarsall.bat x64
。
完成此操作后,我将调用devenv /useenv
。 如果我从命令提示符处执行这些操作,则一切正常,并且可以执行VS中需要做的事情。 我这样做的python代码是:
import os
vcdir=os.environ['ProgramFiles(x86)']
arch = 'x64'
command = 'CALL "' +vcdir+'\\Microsoft Visual Studio 11.0\\VC\\vcvarsall.bat" '+arch
os.system(command)
command = "CALL devenv /useenv"
os.system(command)
如果运行此命令,bat文件将运行,当它尝试使用devenv
命令时,我得到它无法识别。 看起来文件运行在与脚本运行所在的子进程不同的子进程中。我确实需要在当前进程中运行它。 我最终的目标是在python脚本内完成整个构建,并且会有很多调用devenv
来完成构建的主要部分。
谢谢。
我和你有完全一样的问题。 我试图将vcvarsall.bat作为python编写的构建脚本的一部分运行,并且我需要vcvarsall创建的环境。 我找到了一种方法。 首先创建一个名为setup_environment.bat的包装器脚本:
call "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" amd64
set > environment.txt
然后在您将调用vcvarsall.bat的python脚本中,运行包装器脚本,然后将文本文件中的环境变量读取到当前环境中:
this_dir = os.path.dirname(os.path.realpath(__file__)) # path of the currently executing script
os.system('call ' + this_dir + '\setup_environment.bat') # run the wrapper script, creates environment.txt
f = open('environment.txt','r')
lines = f.read().splitlines()
f.close()
os.remove('environment.txt')
for line in lines:
pair = line.split('=',1)
os.environ[pair[0]] = pair[1]
您尝试做的事行不通。 vcvarsall.bat
设置仅在特定进程内工作的环境变量。 而且,Python进程无法在同一进程空间内运行CMD.exe
进程。
我为您提供几种解决方案。
一种是运行vcvarsall.bat
,然后找出它设置的所有环境变量,然后让Python为您设置它们。 您可以使用命令set > file.txt
从CMD Shell中保存所有环境变量,然后编写Python代码来解析此文件并设置环境变量。 可能是太多的工作。
另一种是制作一个运行vcvarsall.bat
的批处理文件,然后从该批处理文件内部启动一个新的Python解释器。 新的Python解释器将处于新进程中,但它将是CMD.exe
进程下的CMD.exe
进程,并且它将继承所有环境变量。
或者,嗯。 也许最好的办法就是编写一个运行vcvarsall.bat
的批处理文件,然后运行devenv
命令。 是的,这可能是最简单的,简单也很好。
需要注意的重要一点是,在Windows批处理文件语言(及其之前的DOS批处理文件)中,当您执行另一个批处理文件时,由另一个批处理文件设置的变量将在同一环境中设置。 在* NIX中,您需要使用特殊的命令source
来在相同的环境中运行Shell脚本,但是批处理就是这样工作的。 但是,在进程终止后,您将永远不会保留变量。
在@ derekswanson08的答案的基础上,我想到了这个功能,它更加成熟。 使用VS 2017随附的wvwhere.exe。
def init_vsvars():
cprint("")
cprint_header("Initializing vs vars")
if "cygwin" in platform.system().lower():
vswhere_path = "${ProgramFiles(x86)}/Microsoft Visual Studio/Installer/vswhere.exe"
else:
vswhere_path = r"%ProgramFiles(x86)%/Microsoft Visual Studio/Installer/vswhere.exe"
vswhere_path = path.expandvars(vswhere_path)
if not path.exists(vswhere_path):
raise EnvironmentError("vswhere.exe not found at: %s", vswhere_path)
vs_path = common.run_process(".", vswhere_path,
["-latest", "-property", "installationPath"])
vs_path = vs_path.rstrip()
vsvars_path = os.path.join(vs_path, "VC/Auxiliary/Build/vcvars64.bat")
env_bat_file_path = "setup_build_environment_temp.bat"
env_txt_file_path = "build_environment_temp.txt"
with open(env_bat_file_path, "w") as env_bat_file:
env_bat_file.write('call "%s"\n' % vsvars_path)
env_bat_file.write("set > %s\n" % env_txt_file_path)
os.system(env_bat_file_path)
with open(env_txt_file_path, "r") as env_txt_file:
lines = env_txt_file.read().splitlines()
os.remove(env_bat_file_path)
os.remove(env_txt_file_path)
for line in lines:
pair = line.split("=", 1)
os.environ[pair[0]] = pair[1]
另一个解决方案是在与build命令相同的os.system中调用vcvarsall.bat:
os.system("cd " + vcFolder + " & vcvarsall.bat amd64 & cd " + buildFolder + " & make")
这是一个简单的示例,应该可以立即使用:
import os
import platform
def init_vsvars():
vswhere_path = r"%ProgramFiles(x86)%/Microsoft Visual Studio/Installer/vswhere.exe"
vswhere_path = os.path.expandvars(vswhere_path)
if not os.path.exists(vswhere_path):
raise EnvironmentError("vswhere.exe not found at: %s", vswhere_path)
vs_path = os.popen('"{}" -latest -property installationPath'.format(vswhere_path)).read().rstrip()
vsvars_path = os.path.join(vs_path, "VC\\Auxiliary\\Build\\vcvars64.bat")
output = os.popen('"{}" && set'.format(vsvars_path)).read()
for line in output.splitlines():
pair = line.split("=", 1)
if(len(pair) >= 2):
os.environ[pair[0]] = pair[1]
if "windows" in platform.system().lower():
init_vsvars()
os.system("where cl.exe")
请注意,在退出python脚本后,环境变量无效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.