我希望我的Python脚本在退出之前暂停使用类似于:
的内容 raw_input("Press enter to close.")
但仅限于不通过命令行运行。命令行程序不应该这样。
有没有办法确定我的Python脚本是否是从命令行调用的:
$ python myscript.py
双击myscript.py
并使用操作系统中的默认解释器打开它?
答案 0 :(得分:14)
如果您在没有终端的情况下运行它,就像在Nautilus中单击“运行”一样,您可以检查它是否附加到tty:
import sys
if sys.stdin.isatty():
# running interactively
print "running interactively"
else:
with open('output','w') as f:
f.write("running in the background!\n")
但是,正如ThomasK所指出的那样,你似乎指的是在程序结束后关闭的终端中运行它。我认为没有解决办法就没办法做你想做的事;程序在常规shell中运行并附加到终端。立即退出的决定是在它完成后没有随时可用的信息(传递给执行的shell或终端的参数)之后完成的。
你可以去examining the parent process information并检测两种调用之间的差异,但在大多数情况下它可能不值得。您是否考虑过在命令行中添加命令行参数(想想--interactive
)?
答案 1 :(得分:4)
我认为没有任何可靠的方法来检测这种情况(特别是以跨平台的方式)。例如,在OS X上,双击.py
文件并使用“Python Launcher”进行调整时,它会在终端中运行,与手动执行时相同。
虽然它可能有其他问题,但您可以使用py2exe或Platypus之类的方法打包脚本,然后您可以使用双击图标运行特定的代码来区分({ {1}}例如)
答案 2 :(得分:2)
如果你运行python IDLE,那么“pythonw.exe”用于运行编码,而当你运行命令行时,“python.exe”用于运行编码。 python文件夹路径可能会有所不同,因此您必须还原python文件夹的路径。 m ='\\'和m = m [0]是因为转义而使m变为'\'。
import sys
a = sys.executable
m = '\\'
m = m[0]
while True:
b = len(a)
c = a[(b - 1)]
if c == m:
break
a = a[:(b - 1)]
if sys.executable == a + 'pythonw.exe':
print('Running in Python IDLE')
else:
print('Running in Command line')
答案 3 :(得分:2)
我想要的在这里得到了回答:Determine if the program is called from a script in Python
您可以在“ python”和“ bash”之间确定。我认为已经回答了这个问题,但是您也可以将其简短。
#!/usr/bin/python
# -*- coding: utf-8 -*-
import psutil
import os
ppid = os.getppid() # Get parent process id
print(psutil.Process(ppid).name())
答案 4 :(得分:1)
这通常是手动完成的,我不认为有一种自动方式可以适用于每种情况。
您应该在脚本中添加一个--pause
参数,以便在最后提示输入密钥。
当手动从命令行调用脚本时,如果需要,用户可以添加--pause
,但默认情况下不会有任何等待。
从图标启动脚本时,图标中的参数应包含--pause
,以便等待。遗憾的是,您需要记录此选项的使用,以便用户知道在创建图标时需要添加该选项,或者在脚本中提供适用于目标操作系统的图标创建功能。
答案 5 :(得分:1)
我的解决方案是使用setuptools创建命令行脚本。以下是myScript.py的相关部分:
def main(pause_on_error=False):
if run():
print("we're good!")
else:
print("an error occurred!")
if pause_on_error:
raw_input("\nPress Enter to close.")
sys.exit(1)
def run():
pass # run the program here
return False # or True if program runs successfully
if __name__ == '__main__':
main(pause_on_error=True)
setup.py的相关部分:
setup(
entry_points={
'console_scripts': [
'myScript = main:main',
]
},
)
现在,如果我使用Python解释器(在Windows上)打开myScript.py,则控制台窗口会等待用户在发生错误时按Enter键。在命令行中,如果我运行'myScript',程序将永远不会在关闭之前等待用户输入。
答案 6 :(得分:1)
我相信这可以做到。至少,这是我在Ubuntu 14.04下使用Python 2.7的方法:
#!/usr/bin/env python
import os, psutil
# do stuff here
if psutil.Process(os.getpid()).parent.name == 'gnome-terminal':
raw_input("Press enter to close...")
请注意 - 在Ubuntu 14中使用Gnome桌面(也称为Nautilus) - 您可能需要这样做:
要了解这是如何工作的,你可以摆弄这个(根据@EduardoIvanec的回答):
#!/usr/bin/env python
import os
import sys
import psutil
def parent_list(proc=None, indent=0):
if not proc:
proc = psutil.Process(os.getpid())
pid = proc.pid
name = proc.name
pad = " " * indent
s = "{0}{1:5d} {2:s}".format(pad, pid, name)
parent = proc.parent
if parent:
s += "\n" + parent_list(parent, indent+1)
return s
def invoked_from_bash_cmdline():
return psutil.Process(os.getpid()).parent.name == "bash"
def invoked_as_run_in_terminal():
return psutil.Process(os.getpid()).parent.name == "gnome-terminal"
def invoked_as_run():
return psutil.Process(os.getpid()).parent.name == "init"
if sys.stdin.isatty():
print "running interactively"
print parent_list()
if invoked_as_run_in_terminal():
raw_input("Type enter to close...")
else:
with open('output','w') as f:
f.write("running in the background!\n")
f.write("parent list:\n")
f.write(parent_list())
答案 7 :(得分:0)
虽然这不是一个非常好的解决方案,但它确实有效(至少在Windows中)。
您可以使用以下内容创建批处理文件:
@echo off
for %%x in (%cmdcmdline%) do if /i "%%~x"=="/c" set DOUBLECLICKED=1
start <location of python script>
if defined DOUBLECLICKED pause
如果您希望能够使用单个文件执行此操作,可以尝试以下操作:
@echo off
setlocal EnableDelayedExpansion
set LF=^
:: The 2 empty lines are necessary
for %%x in (%cmdcmdline%) do if /i "%%~x"=="/c" set DOUBLECLICKED=1
echo print("first line of python script") %LF% print("second and so on") > %temp%/pyscript.py
start /wait console_title pyscript.py
del %temp%/pyscript.py
if defined DOUBLECLICKED pause
批量代码来自:Pausing a batch file when double-clicked but not when run from a console window? 批量多行来自:DOS: Working with multi-line strings
答案 8 :(得分:0)
好的,我发现和制作的最简单方法是在命令行中运行程序,即使它是在Python IDLE中运行的。
exist = lambda x: os.path.exists(x) ## Doesn't matter
if __name__ == '__main__':
fname = "SomeRandomFileName" ## Random default file name
if exist(fname)==False: ## exist() is a pre-defined lambda function
jot(fname) ## jot() is a function that creates a blank file
os.system('start YourProgram.py') ## << Insert your program name here
os.system('exit'); sys.exit() ## Exits current shell (Either IDLE or CMD)
os.system('color a') ## Makes it look cool! :p
main() ## Runs your code
os.system("del %s" % fname) ## Deletes file name for next time
将其添加到脚本的底部,一旦从IDLE或命令提示符运行,它将创建一个文件,在CMD中重新运行该程序,并退出第一个实例。 希望有所帮助! :)
答案 9 :(得分:0)
从this回答背后的想法,添加Win10兼容性(从Python 2.7脚本中删除;根据需要修改):
import os, psutil
status = 1
if __name__ =="__main__":
status = MainFunc(args)
args = sys.argv
running_windowed = False
running_from = psutil.Process(os.getpid()).parent().name()
if running_from == 'explorer.exe':
args.append([DEFAULT OR DOUBLE CLICK ARGS HERE])
running_windowed = True
if running_windowed:
print('Completed. Exit status of {}'.format(status))
ready = raw_input('Press Enter To Close')
sys.exit(status)
您可以添加许多类似于开关的语句,以使其更具通用性或处理不同的默认值。
答案 10 :(得分:0)
我也有这个问题,对我来说,最好的解决方案是在我的IDE(PyCharm)中设置一个环境变量,并检查该变量是否存在,以通过命令行或通过IDE。
要在PyCharm中设置环境变量,请检查: How to set environment variables in PyCharm?
示例代码(环境变量:RUNNING_PYCHARM = True):
import os
# The script is being executed via the command line
if not("RUNNING_PYCHARM" in os.environ):
raw_input("Press enter to close.")
我希望它适合你。