0

我在Windows上。我正在尝试编写一个 Python 2.x 脚本(我们称之为setup.py),它将启用以下场景:

  1. 用户运行 cmd 打开控制台窗口
  2. 在该控制台窗口中,用户运行setup.py
  3. 用户发现自己在同一个控制台窗口中,但现在在那里运行的 cmd 的环境(环境变量)已被修改setup.py

setup.pyFOO通过添加一个带有 value的新环境变量foo并在 . 中添加一些东西来修改环境PATH

在 Linux 上,我会简单地使用os.exec*e配置环境的 shell 替换 Python 进程。

我在 Windows 上尝试了相同的方法(如os.exec*e(os.environ['ComSpec'])),但它不起作用,新执行的 cmd 的环境是这样的:

  • 运行只是set没有列出FOO,也没有显示对PATH. 跑步set FOO,然而,显示FOO=fooecho %FOO%回声foo

  • 运行set PATHecho %PATH%显示修改后的PATH变量。在没有修改的情况下运行set pathecho %path%显示值(即使环境变量在 Windows 上通常不区分大小写)。

  • 如果我输入exit,conole 将保持挂起状态,不接受输入,直到我点击Ctrl+C. 之后,它显然又回到了cmd最初调用的那个setup.py

很明显,os.exec*e不适用于 Windows 上的这种情况。有没有不同的方法来实现我想要的?是否有subprocess.Popen()标志组合可以让我退出调用 Python 进程并让被调用的 cmd 运行,最好是在同一个控制台中?还是会CreateProcess通过ctypes帮助访问?

如果有必要,我会满足于启动一个新的控制台窗口并关闭旧的,但我当然不能让旧的控制台窗口处于冻结状态,等待新创建的窗口关闭。

4

1 回答 1

2

如果在脚本之外使用 Windows 批处理文件是可以接受的,那么有一个更简单的解决方案,因为批处理文件在调用进程中运行,因此可以修改其环境。

给定一个文件setup.bat,它看起来像这样......

@echo off
for /f "tokens=*" %%a in ('python setup.py') do %%a

...和一个setup.py看起来像这样的文件...

import os
print 'set FOO=foo'
print 'set PATH=%s;%s' % ('C:\\my_path_dir', os.environ['PATH'])

...并假设python.exe在 PATH 中,然后setup.bat从命令行调用将在调用过程中设置环境变量,同时仍然允许您使setup.py脚本尽可能复杂,只要它打印您想要的命令执行到标准输出。

根据评论更新

如果您setup.py有多种操作模式,则可以为其制作setup.bat通用包装器。假设setup.bat看起来像这样......

@echo off
if "%1" == "setenv" (
    for /f "tokens=*" %%a in ('python setup.py %1') do %%a
) else (
    python setup.py %*
)

......setup.py看起来像这样......

import sys
import os

if len(sys.argv) > 1 and sys.argv[1] == 'setenv':
    print 'set FOO=foo'
    print 'set PATH=%s;%s' % ('C:\\my_path_dir', os.environ['PATH'])
else:
    print "I'm gonna do something else with argv=%r" % sys.argv

……这还不够吗?

于 2013-04-11T11:32:17.247 回答