Проверка за интерактивна обвивка в скрипт на Python

Трябва да определя дали обвивката, която извика моя Python скрипт, е била в интерактивен режим или не. Ако беше в интерактивен режим, програмата трябваше да изведе изхода към less(1) за лесно четене. Ако не, той трябва просто да отпечата изхода си в stdout, за да може да бъде прехвърлен към принтер, файл или друг пейджър.

В скрипт на обвивка бих проверил дали променливата за подкана $PS1 е дефинирана или бих потърсил опцията -i сред флаговете, съхранени в променливата $-.

Какъв е предпочитаният метод за тестване на интерактивност от Python?


person jforberg    schedule 24.05.2011    source източник


Отговори (5)


Това често работи достатъчно добре

import os, sys
if os.isatty(sys.stdout.fileno()):
    ...
person John La Rooy    schedule 24.05.2011
comment
sys.stdout.isatty() е по-къс. - person lunaryorn; 24.05.2011
comment
И sys.__stdin__.isatty() по-надежден. (не се влияе от stdin пренасочване и позволява извеждане) - person Evpok; 24.05.2011
comment
@Evpok: OP поиска stdout, stdin е напълно несвързан. За да разберете дали да страница извежда или не, stdin наистина е грешният поток за проверка, защото потребителят може да прехвърли нещо в програмата (по този начин пренасочва stdin и го изключва от tty) и пак искате да видите изхода в пейджър (тъй като stdout не се пренасочва). - person lunaryorn; 24.05.2011
comment
@Evpok, имаш предвид sys.__stdout__.isatty(). Възможно е изходът да бъде tty, когато входът не е и OP изглежда се интересува от изхода - person John La Rooy; 24.05.2011
comment
@lunaryom Да, знам. Но той написа. Ако беше в интерактивен режим, програмата трябва да изпрати изхода към less(1) за лесно четене за мен, това означава, че той проверява stdin и пренасочва stdout според естеството му. - person Evpok; 24.05.2011
comment
@Evpok, @lunaryom Правя програма в стил man(1). Искам да се държи приблизително като човек, т.е. да препраща изход към less(1), ако е интерактивен, но просто да го отпечата, ако не. Така че вероятно искам да проверя дали stdout е tty. - person jforberg; 24.05.2011

От тази връзка можете да използвате същия начин и да тествате дали stdin е свързан с terminate(tty), можете да направите това с помощта на os.isatty() , пример:

>>> os.isatty(0)
True

N.B: От същата връзка това ще се провали, когато извикате командата дистанционно чрез ssh, даденото решение е да се тества дали stdin е свързан с канал.

person mouad    schedule 24.05.2011
comment
Предпочитам по-очевидното sys.__stdin__.isatty() - person Evpok; 24.05.2011
comment
@Evpok: Да, съгласен съм, забравих за метода на файловия обект isatty(), благодаря :) - person mouad; 24.05.2011
comment
Това изглежда е еквивалентно на отговора на gnibbler, с изключение на това, че читателят трябва да познава достатъчно unix, за да знае, че файл 0 е stdin. Има ли разлика между проверката на isatty() на stdin или stdout, мислите ли? - person jforberg; 24.05.2011
comment
@jforberg: да, съгласен съм и мисля, че най-добрият е коментарът на @Evpok, sys.__stdin__.isatty() и интерактивният режим AFAIK означава, че stdin е асоцииран към терминала, а не към stdout, поправете ме, ако греша :) - person mouad; 24.05.2011
comment
Да, решението на Evpok е най-елегантното и читаво в моите очи. Благодаря! - person jforberg; 24.05.2011

Ако вече имате зависимост от matplotlib или нямате нищо против да въведете такава, винаги можете просто да извикате matplotlib.is_interactive()

person schwartrer    schedule 15.12.2012
comment
Вижте ред 1049 на github.com/matplotlib/matplotlib/blob /master/lib/matplotlib/ . is_interactive() просто чете глобална променлива в matplotlib. Не виждам гаранции, че ще се отнася до интерактивността на родителската обвивка. - person jforberg; 16.12.2012

if sys.flags.interactive:
    #interactive
else:
    #not interactive 

http://docs.python.org/library/sys.html#sys.flags

person Pych    schedule 29.07.2011
comment
Това води до true само ако Python е стартиран с опцията -i. Стартирането му с опцията -i ще пусне Python в режим на интерпретатор след стартиране на скрипта. sys.flags.interactive не може да се използва за определяне на естеството на текущата среда на обвивката. - person chiborg; 12.10.2011

Правя капак клас за тестване.

Например имате:

class SuperInteractiveClass(object):
   def get_data_from_stdin(self):
      '... a lot of code here ...'
   '... and a lot of other function'

Правя втори клас, само за проба

class TestSuperInteractiveClass(SuperInteractiveClass):
    prepared_data = []
    def add_prepared_data(self,data):
        self.prepared_data.append(data)
    def get_data_from_stdin(self):
          return self.prepared_data.pop(0)
person Oduvan    schedule 24.05.2011
comment
аз не разбирам Какъв е смисълът от това? Как това проверява интерактивността на invoker? - person Evpok; 24.05.2011
comment
Не е, поне не по начин, който мога да разбера. Изглежда, че е внедрил стек. - person jforberg; 24.05.2011