Подтвердить что ты не робот

Как определить, был ли запущен Python script через командную строку?

Фон

Я хочу, чтобы мой Python script приостанавливался, прежде чем выходить, используя что-то похожее на:

raw_input("Press enter to close.")

но только если он НЕ запускается через командную строку. Программы командной строки не должны вести себя таким образом.

Вопрос

Есть ли способ определить, был ли мой Python script выведен из командной строки:

$ python myscript.py

стихи двойным щелчком myscript.py, чтобы открыть его с помощью интерпретатора по умолчанию в ОС?

4b9b3361

Ответ 1

Я не думаю, что есть надежный способ обнаружить это (особенно в кросс-платформенной манере). Например, в OS X, когда вы дважды щелкаете по файлу .py и настраиваете его с помощью "Python Launcher", он запускается в терминале, идентично, если вы выполняете его вручную.

Хотя у него могут быть и другие проблемы, вы можете упаковать script с чем-то вроде py2exe или Platypus, тогда вы можете использовать значок с двойным щелчком для запуска определенного бита кода для дифференциации (import mycode; mycode.main(gui = True) например)

Ответ 2

Если вы используете его без терминала, как при нажатии кнопки "Выполнить" в 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, вы, похоже, ссылаетесь на запуск его в терминале, который закрывается сразу после завершения программы. Я думаю, что нет способа сделать то, что вы хотите, без обходного пути; программа работает в обычной оболочке и прикрепляется к терминалу. Решение о выходе немедленно выполняется сразу после того, как оно заканчивается с информацией, которую он не имеет легкодоступной (параметры передаются исполняющей оболочке или терминалу).

Вы можете охарактеризовать информацию о родительском процессе и обнаружить различия между двумя типами вызовов, но в большинстве случаев это, вероятно, не стоит. Рассматривали ли вы добавление параметра командной строки в script (think --interactive)?

Ответ 3

Если вы запустите 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')

Ответ 4

Я считаю, что это МОЖЕТ быть сделано. По крайней мере, вот как я получил его в Python 2.7 под Ubuntu 14.04:

#!/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 (aka Nautilus) - вам может понадобиться сделать это:

  • из окна Nautilus (браузер файлов) выберите "Редактировать" (меню) → "Настройки" (пункт), затем "Поведение" (вкладка) → "Исполняемые текстовые файлы" (раздел) → "Запросить каждое время" (радио).
  • chmod your script для выполнения или из окна Nautilus (браузер файлов) - щелкните правой кнопкой мыши по файлу- > Свойства (элемент), затем выберите Разрешения (вкладка) → Выполнить: разрешить выполнение файла как программа (галочка)
  • дважды щелкните файл. Если вы выберете "Запустить в терминале", вы увидите сообщение "Введите ввод, чтобы закрыть...".
  • попробуйте выполнить запрос bash; вы не должны видеть приглашение.

Чтобы понять, как это работает, вы можете играть с этим (на основе ответа от @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())

Ответ 5

Обычно это делается вручную /, я не думаю, что есть автоматический способ сделать это, который работает для каждого случая.

Вы должны добавить аргумент --pause к вашему script, который вызывает подсказку для ключа в конце.

Когда script вызывается из командной строки вручную, пользователь может добавить --pause, если это необходимо, но по умолчанию ждать не будет.

Когда script запускается из значка, аргументы в значке должны содержать --pause, так что есть ожидание. К сожалению, вам нужно будет либо документировать использование этой опции, чтобы пользователь знал, что ее нужно добавить при создании значка, либо создать функцию создания значков в script, которая работает для вашей целевой ОС.

Ответ 6

Мое решение заключалось в создании сценариев командной строки с помощью 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',
        ]
    },
)

Теперь, если я открою myScript.py с помощью интерпретатора Python (в Windows), консольное окно ждет, когда пользователь нажмет клавишу enter, если возникла ошибка. В командной строке, если я запустил "myScript", программа никогда не будет ждать ввода пользователя перед закрытием.

Ответ 7

Из идеи этого ответьте, добавив для совместимости с Win10 (Ripped from Python 2.7 script; измените по мере необходимости):

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)

Существует ряд операторов, похожих на switch, которые вы можете добавить, чтобы быть более универсальными или обрабатывать разные значения по умолчанию.

Ответ 8

Хотя это не очень хорошее решение, оно работает (по крайней мере, в окнах).

Вы можете создать пакетный файл со следующим содержимым:

@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

Пакетный код из: Приостановка пакетного файла при двойном щелчке, но не при запуске из окна консоли? Многострочный пакет из DOS: работа с многострочными строками

Ответ 9

Хорошо, самый простой способ, который я нашел и сделал, - просто запустить программу в командной строке, даже если она была запущена в 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

Добавьте это в конец вашего script и один раз запускайтесь из IDLE или командной строки, он создаст файл, запустит программу в CMD и выйдет из первого экземпляра. Надеюсь, это поможет!:)

Ответ 10

У меня также был этот вопрос, и для меня лучшим решением было установить переменную среды в моей среде IDE (PyCharm) и проверить, существует ли эта переменная, чтобы узнать, выполняется ли script либо через командную строку, либо через IDE.

Чтобы установить переменную среды в PyCharm, проверьте: Как установить переменные среды в 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.")

Я надеюсь, что это сработает для вас.