【问题标题】:Why are os.system and subprocess.call spawning so many processes?为什么 os.system 和 subprocess.call 会产生这么多进程?
【发布时间】:2013-08-11 20:25:35
【问题描述】:
import os
import subprocess
import sys
import re

## fname_ext=sys.argv[1]
fname_ext=r"C:\mine\.cs\test.cs"
exe=os.path.splitext(fname_ext)[0]+".exe" # Executable
fdir=os.path.split(fname_ext)[0]
fcontent=open(fname_ext).read()

p_using=re.compile("\s*using\s+((\w+[.]*)+)")
p_namespace=re.compile("\s*namespace\s+(\w+)")
usings=p_using.findall(fcontent)
usings=[x[0] for x in usings]
references=[]
for i in os.listdir(fdir):
    path=fdir+"\\"+i
    try:
        if os.path.isdir(path) or (not path.endswith('cs')):continue
        with open(path) as fp:
            content=fp.read()
            namespaces=p_namespace.findall(content)
            for n in namespaces:
                if n in usings and 'System' not in n:
                    references+=[path]
    except:
        pass

command="csc /nologo "+" ".join(references)+" "+fname_ext
## command=" ".join(references)
#~ ---------------------------------------------------------
# Build:
option=1
if option==0:
    # using os.system
    print ">>",command
    if os.system(command)==0:
        os.system(exe)
else:
    #~ Using subprocess module
    ## print type(references)
    command=['csc']
    ## print command,references
    command.extend(["/nologo","/out:"+exe])
    command.extend(references)
    command.append(fname_ext)
    ## print command
    if subprocess.call(command,shell=True)==0:
        ## print "running %s"%exe
        subprocess.call([exe],shell=True)
    else:
        pass
        ## print "Failed to run"
#~ ---------------------------------------------------------

我上面有这段代码,它应该从SciTE 运行一个 Csharp 程序。它搜索
目录中的每个.cs 文件,并找到具有当前
文件已包含。在 SciTE 中运行文件的命令是:
command.go.*.cs=python C:\mine\.py\csc.py $(FilePath)
command.go.subsystem.*.cs=0

那个程序逻辑部分没问题。
问题是,当使用如下示例 Csharp 代码按 F5 时:

using System;
using System.Collections;
using MyNamespace;
class Test{
    public static void Main(String[] args){
        MyObject inst=new MyObject();
        MyObject.self_destruct(inst);
    }
}

运行正常。但是当我取消注释第二个 fname_ext 并评论第一个时
并运行 csc.py 文件,打开一个窗口并继续运行,打印 command(发生这种情况
使用os.system 选项)。当您使用 the subprocess.call 选项时,同样的事情
但这一次只有在shell=True 时才会发生。它只运行了 15 秒,就有 800+ cmd.exe 和 python.exe 进程。杀死 cmd.exe 后我不得不等待将近 5 分钟
让鼠标开始响应,再过 2 分钟让桌面窥视工作。
shell=False 时,它运行正常,就像您从文件中按 F5 键时一样。
这里发生了什么?
shell=True 在做什么这让它表现得那样吗?

【问题讨论】:

  • 您能否记录足够的信息以查看每种情况下的sys.argv 是什么?因为显而易见的猜测是您正在运行自己的脚本,而不是您真正想要运行的东西。
  • 实际上,Scite 是传递给 sys.argv($(FilePath)) 的那个。它传递字符串“C:\mine\.cs\test.cs”。我创建了第二个 fname_ext 以便在测试时可以在两者之间切换。当我运行 csc.py 和运行 test.cs 时,它输出相同的结果,所以我不认为我在运行自己的脚本。即使是同一个脚本,无论 shell 参数的值如何,结果都是相似的。

标签: python subprocess os.system scite


【解决方案1】:

问题是您的sys.argv 看起来像这样:

['python', r'C:\mine\.py\csc.py', 'whatever.cs']

因此,在取消注释 fname_ext 行的情况下,您将 fname_ext 设置为 r'C:\mine\.py\csc.py'。这意味着您的脚本最终只会运行自己——它会再次运行自己,等等,尽可能快地运行,直到您的系统阻塞。

shell=False 不会发生这种情况的原因是您实际上无法执行 Python 脚本。最终,您最终使用您的脚本调用CreateProcess,该脚本试图将其解释为 .exe 文件,但失败并返回错误。但是使用shell=True,您将脚本传递给cmd.exe 以作为程序运行, 会做与交互式提示或资源管理器相同的事情:找到正确的映射来执行 .py 文件并使用它。 (os.systemshell=True 做的事情实际上是一样的,但为了更好地衡量,还增加了几个额外的层。)

【讨论】:

  • 我有点困惑。当我打开 test.cs 选项卡并运行它时,SciTE 将文件路径传递给脚本,即 python C:\mine\.py\csc.py C:\mine\.cs\test.cs 。 sys.argv[1] 不会仍然是文件路径(脚本使用)并且 sys.argv[0] 不会是脚本的名称(csc.py)。我在列表中看到第三个项目,怎么样?
【解决方案2】:

好的,我会尝试一下。如果我理解这种情况,这个脚本叫做 csc.py,你想调用 csc c# 编译器。当您通过 cmd.exe 运行 csc /nologo (etc...) 时,它会开始寻找具有已知扩展名的名为“csc”的东西。它在当前目录中找到 csc.py 并且由于 .py 是一个注册的扩展名,这就是被执行的内容。

解决方案是重命名您的 python 文件或显式调用“csc.exe”。

【讨论】:

  • 我觉得自己很愚蠢。当我将它重命名为 casc.py(meaningless) 时它会起作用。我正在运行我自己的脚本,只是不是那么明显。 @abarnet 部分正确。如果您从 %PATHEXT% 取消注册 .PY 扩展名,它也会运行(不过这毫无意义)。如果你结合这两个答案,你会得到完整的解释。谢谢。
猜你喜欢
  • 2014-10-19
  • 1970-01-01
  • 2018-03-03
  • 2012-08-08
  • 2013-05-22
  • 2018-08-17
  • 1970-01-01
  • 2013-03-10
  • 2013-09-04
相关资源
最近更新 更多