【问题标题】:Detect script start up from command prompt or "double click" on Windows检测脚本从命令提示符启动或在 Windows 上“双击”
【发布时间】:2009-02-17 21:20:24
【问题描述】:

是否可以检测 Python 脚本是从命令提示符启动还是通过用户“双击”Windows 文件资源管理器中的 .py 文件启动的?

【问题讨论】:

    标签: python windows


    【解决方案1】:

    如果从命令行运行,则定义了一个额外的环境变量“PROMPT”。

    如果从资源管理器单击此脚本将暂停,如果从命令行运行则不会暂停:

    import os
    
    print 'Hello, world!'
    
    if not 'PROMPT' in os.environ:
        raw_input()
    

    使用 Python 2.7 在 Windows 7 上测试

    【讨论】:

    • 测试两个关键字PROMPTTCL_LIBRARY。启动 1) python shell, 2) 双击 .py 文件 3) windows cmd: i.stack.imgur.com/CbFUT.jpg
    【解决方案2】:

    这里是一个如何获取当前运行脚本的父进程id和名称的例子。正如Tomalak 所建议的那样,这可用于检测脚本是从命令提示符启动还是通过在资源管理器中双击启动。

    import win32pdh
    import os
    
    def getPIDInfo():
        """ 
        Return a dictionary with keys the PID of all running processes.
        The values are dictionaries with the following key-value pairs:
            - name: <Name of the process PID>
            - parent_id: <PID of this process parent>
        """
    
        # get the names and occurences of all running process names
        items, instances = win32pdh.EnumObjectItems(None, None, 'Process', win32pdh.PERF_DETAIL_WIZARD)
        instance_dict = {}
        for instance in instances:
            instance_dict[instance] = instance_dict.get(instance, 0) + 1
    
        # define the info to obtain 
        counter_items =  ['ID Process', 'Creating Process ID']
    
        # output dict
        pid_dict = {}
    
        # loop over each program (multiple instances might be running)
        for instance, max_instances in instance_dict.items():
            for inum in xrange(max_instances):
                # define the counters for the query 
                hq = win32pdh.OpenQuery()
                hcs = {}
                for item in counter_items:
                    path = win32pdh.MakeCounterPath((None,'Process',instance, None,inum,item))
                    hcs[item] = win32pdh.AddCounter(hq,path)
                win32pdh.CollectQueryData(hq)
    
                # store the values in a temporary dict
                hc_dict = {}
                for item, hc in hcs.items():
                    type,val=win32pdh.GetFormattedCounterValue(hc,win32pdh.PDH_FMT_LONG)
                    hc_dict[item] = val
                    win32pdh.RemoveCounter(hc)
                win32pdh.CloseQuery(hq)
    
                # obtain the pid and ppid of the current instance
                # and store it in the output dict
                pid, ppid = (hc_dict[item] for item in counter_items) 
                pid_dict[pid] = {'name': instance, 'parent_id': ppid}
    
        return pid_dict
    
    def getParentInfo(pid):
        """
        Returns a PID, Name tuple of the parent process for the argument pid process.
        """
        pid_info = getPIDInfo()
        ppid = pid_info[pid]['parent_id']
        return ppid, pid_info[ppid]['name']
    
    if __name__ == "__main__":
        """
        Print the current PID and information of the parent process.
        """
        pid = os.getpid()
        ppid, ppname = getParentInfo(pid)
    
        print "This PID: %s. Parent PID: %s, Parent process name: %s" % (pid, ppid, ppname)
        dummy = raw_input()
    

    当从命令提示符运行时,输出:

    此 PID:148。父 PID:4660,父进程名称:cmd

    当在资源管理器中双击启动时,输出:

    此 PID:1896。父 PID:3788,父进程名称:资源管理器

    【讨论】:

      【解决方案3】:

      命令提示符启动的脚本有一个名为cmd.exe 的父进程(或不存在的进程,以防控制台同时关闭)。

      双击启动的脚本应该有一个名为explorer.exe的父进程。

      【讨论】:

      • 聪明。你会怎么做?
      • docs.python.org/library/os.html#os.getppid 看来我可以获取进程ID,但不能获取名称。
      • 视情况而定。你有什么可用的工具?您想从 python 脚本内部还是外部进行检查?无论如何,“我如何使用 Python 找出 Win32 进程信息”是一个单独问题的好材料。
      • 经过短暂的谷歌搜索后,win32pdh 模块似乎正是您所需要的。它看起来很有希望。 WMI 也应该完全有能力回答这样的问题
      • Python 3.3+ 默认安装一个启动器(py.exe),它成为双击启动脚本的父进程。
      【解决方案4】:

      好问题。您可以做的一件事是在 Windows 中创建脚本的快捷方式,并传递参数(使用快捷方式的 Target 属性),表明脚本是通过双击启动的(在本例中为快捷方式)。

      【讨论】:

        【解决方案5】:

        我将这个小函数 (pybyebye()) 放在我的一些程序中的 return 语句之前。我已经在我的台式机和笔记本电脑上的 Windows 10 下对其进行了测试,它可以满足我的需求,即只有在文件资源管理器中双击程序启动程序时,它才会暂停等待用户输入。这可以防止临时命令窗口在用户说之前消失。在 Linux 下,它什么也不做。反正没坏处!在 Mac 上也是如此。

        ##  PYBYEBYE :
        def pybyebye (eprompt="PROMPT",efps="FPS_BROWSER_"):
            "nice exit in Windows according to program launch from: IDLE, command, clix."
        
        ##  first examine environment (os & sys having been imported) :
        ui = None
        platform = sys.platform
        ##  print("os =",platform)
        if not platform.lower().startswith("win"):
            return  ui  ##  only relevant in windows
        fromidle = False
        launched = "Launched from"
        if sys.executable.endswith("pythonw.exe"):
            fromidle = True  ##  launched from within IDLE
        envkeys = sorted(os.environ)
        prompter = eprompt in envkeys
        browser = False
        for ek in envkeys:
            ##  print(ek)
            if ek.startswith(efps):
                browser = True
                break
        ##  next decide on launch context :
        if fromidle and not prompter:  ##  surely IDLE
            ##  print(launched,"IDLE")
            pass  ##  screen won't disappear
        elif browser and not prompter:  ##  run with double click
            ##  print(launched,"File Explorer")
            print("Press Enter to finish ....") ; ui=input()
        elif prompter and not fromidle:  ##  run from preexisting command window
            ##  print(launched,"Command Window")
            pass  ##  screen won't disappear
        else:  ##  something funny going on, Mac or Linux ??
            print("launch mode undetermined!")
        
        return  ui
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-08-05
          • 2016-05-16
          • 1970-01-01
          • 2013-09-22
          相关资源
          最近更新 更多