Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / PHP, Perl, Python Новый топик    Ответить
 [python] - тонкие отличия os.popen2 и subprocess.Popen  [new]
Vladimir Baskakov
Member

Откуда:
Сообщений: 2006
#1
p=Popen(cmd, bufsize=-1, stdin=PIPE, stdout=PIPE)
self.to_=p.stdin
self.from_=p.stdout
#2        
self.to_, self.from_ = os.popen2(cmd)


коллеги, помогите начинающему питонисту. (использую Python 2.7, windows)
- есть 2 альтернативных способа запуска дочернего процесса.
второй работает хорошо, стабильно, приложения получают ввод и отдают вывод, в первом же варианте одно из приложений работает некорректно. а второе нормально.

Я захотел разобраться почему так, но открыв os.py так и не нашел, где оно для винды затягивает функцию popen2 - нашел только фрагмент для юникса
# Supply popen2 etc. (for Unix)
if _exists("fork"):
    if not _exists("popen2"):
        def popen2(cmd, mode="t", bufsize=-1):
            """Execute the shell command 'cmd' in a sub-process.  On UNIX, 'cmd'"""

и тут стало вообще интересно как это устроено.... если кто подскажет - большое спасибо.

В принципе, работающего варианта пока хватает, но под третьим python-ом оно уже работать перестанет, а было бы неплохо и там тоже.
21 мар 17, 14:36    [20317837]     Ответить | Цитировать Сообщить модератору
 Re: [python] - тонкие отличия os.popen2 и subprocess.Popen  [new]
FishHook
Member [скрыт] [заблокирован]

Откуда:
Сообщений: 35323
Блог
Vladimir Baskakov,

os.popen и остальные его братья - устаревшие методы, его никто их не поддерживает и они крайне не рекомендуются к использованию. Просто забудьте про них и все.

К сообщению приложен файл. Размер - 121Kb
21 мар 17, 19:19    [20318915]     Ответить | Цитировать Сообщить модератору
 Re: [python] - тонкие отличия os.popen2 и subprocess.Popen  [new]
Vladimir Baskakov
Member

Откуда:
Сообщений: 2006
Спасибо .

Но код работает именно с ним. Устаревшим. А с новым глючит. Именно поэтому я и задал вопрос - я хочу заменить на новое, но чтобы работало, а не глючило (((
22 мар 17, 05:44    [20319654]     Ответить | Цитировать Сообщить модератору
 Re: [python] - тонкие отличия os.popen2 и subprocess.Popen  [new]
FishHook
Member [скрыт] [заблокирован]

Откуда:
Сообщений: 35323
Блог
Vladimir Baskakov
А с новым глючит.

Что значит "глючит"?
Дайте минимальный воспроизводимый пример некорректного поведения.
22 мар 17, 07:10    [20319681]     Ответить | Цитировать Сообщить модератору
 Re: [python] - тонкие отличия os.popen2 и subprocess.Popen  [new]
Vladimir Baskakov
Member

Откуда:
Сообщений: 2006
минимального нет.

Есть скрипт
https://github.com/zztrilobit/go_assistant/blob/master/goban.py

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

class GoEngine:
def StartEngin(self,cmd):

- запускает таковую утилиту
def gtp(self, command):
- посылает ей команду и считывает ответ.

Сейчас отладка проходит с двумя движками - GNUGO и leela.

GNUGO независимо от библиотечной функции которая запустила и подключилась к каналам дает правильный ответ.

leela пока нормально коммуницирует только при запуске с помощью os.popen2 а - при запуске через p=Popen(cmd, bufsize=-1, stdin=PIPE, stdout=PIPE)
self.to_=p.stdin
self.from_=p.stdout


в ответ на любую команду дает неправильный ответ который вылавливается тут:
assert(self.from_gnugo.read(1) == "\n") - вот мне любопытно, почему так. Откуда в потоке взялся "\n"

Чтобы воспроизвести, естественно нужно скачивать эту самую леелу, что конечно всем будет лень.... поэтому я задал вопрос более общий :

- где посмотреть исходник устаревшей и новой функции (класса) чтобы найти отличия в работе.
22 мар 17, 09:54    [20320024]     Ответить | Цитировать Сообщить модератору
 Re: [python] - тонкие отличия os.popen2 и subprocess.Popen  [new]
Vladimir Baskakov
Member

Откуда:
Сообщений: 2006
FishHook,

+
from sys import exit as sysexit
from os.path import splitext
import os
from subprocess import *
import time
import popen2

# интерактив с энжином
class GoEngine:
    def __init__(self):
        self._gtpnr = 1
        self.running=False
    
    def StartEngin1(self,cmd):
        print "starting ", cmd
        self.to_gnugo,self.from_gnugo = os.popen2(cmd)
        self.running=True

    def StartEngin2(self,cmd):
        print "starting ", cmd
        p=Popen(cmd, bufsize=-1, stdin=PIPE, stdout=PIPE)
        #p=Popen(["leela080.exe","--gtp"], shell=True, bufsize=-1, stdin=PIPE, stdout=PIPE)
        self.to_gnugo=p.stdin
        self.from_gnugo=p.stdout
        self.running=True
    
    def gtp(self, command):
        if not self.running : 
            # raise BasicError("OOOOPS..... NO GTP ENGINE!!!!")
            print ("OOOOPS..... NO GTP ENGINE!!!!")
            return
        verbose = True
        cmd = str(self._gtpnr) + " " + command
        if verbose:
            print cmd
            sys.stdout.flush()
        self.to_gnugo.write(cmd + "\n")
        self.to_gnugo.flush()
        status = self.from_gnugo.read(1)
        value = status
        while not status == "\n":
            status = self.from_gnugo.read(1)
            value += status
        assert(self.from_gnugo.read(1) == "\n")
        if verbose:
            print value
        retval=value[1 + len(str(self._gtpnr)):]
        #todo - тут надо бы вылавливать ошибки хотя бы так
        self.is_ok=value[0]=="="
        if not self.is_ok:
            print "gtp error!!! "+retval
        self._gtpnr += 1
        return retval
            
    def time_by_move(self, seconds) :
        # всю партию машина играет в режиме байоми, по нужному числу секунд на ход
        return self.gtp("time_settings 1 "+str(seconds)+" 1")

    def quit(self):
        r=self.gtp('quit')
        self.running=False
        return r
        
    def undo(self):
        return self.gtp('undo')

e=GoEngine()
e.StartEngin1("leela080.exe --g")
e.time_by_move(3)
e.quit()
e.StartEngin2("leela080.exe --g")
e.time_by_move(3)
e.quit()

..\python.exe test.py 1>1 2>2

+

Результаты
stdout (1) :
starting leela080.exe --g
1 time_settings 1 3 1
=1

2 quit
=2

starting leela080.exe --g
3 time_settings 1 3 1


stderr (2) :
110 feature weights loaded, 2608 patterns
BLAS core: MKL Intel(R) Streaming SIMD Extensions 4.2 (Intel(R) SSE4.2) enabled processors
Traceback (most recent call last):
File "test.py", line 77, in <module>
e.time_by_move(3)
File "test.py", line 62, in time_by_move
return self.gtp("time_settings 1 "+str(seconds)+" 1")
File "test.py", line 49, in gtp
assert(self.from_gnugo.read(1) == "\n")
AssertionError


коммент - в stderr попал как вывод leela
110 feature weights loaded, 2608 patterns
BLAS core: MKL Intel(R) Streaming SIMD Extensions 4.2 (Intel(R) SSE4.2) enabled processors
Traceback (most recent call last):

так и сообщение об ошибке на assert.

ну и понятно что второй процесс энжина остался висеть в памяти и жрать процессорное время
22 мар 17, 10:27    [20320171]     Ответить | Цитировать Сообщить модератору
 Re: [python] - тонкие отличия os.popen2 и subprocess.Popen  [new]
Vladimir Baskakov
Member

Откуда:
Сообщений: 2006
..... в общем наверное придется делать типа такого....
http://eyalarubas.com/python-subproc-nonblock.html

похоже по простому не выйдет ..... ну или оставить все как есть, на неправильной библиотечке... ((((((((
22 мар 17, 17:10    [20322171]     Ответить | Цитировать Сообщить модератору
 Re: [python] - тонкие отличия os.popen2 и subprocess.Popen  [new]
maxkar
Member

Откуда:
Сообщений: 170
Vladimir Baskakov
похоже по простому не выйдет


Ну я не знаю, зачем вы на неблокирующий ввод/вывод смотрите (он вашу проблему не решит все равно).

Вам по идее банальное
p=Popen(cmd, bufsize=-1, stdin=PIPE, stdout=PIPE, universal_newlines=True)

нужно.
23 мар 17, 22:50    [20327725]     Ответить | Цитировать Сообщить модератору
 Re: [python] - тонкие отличия os.popen2 и subprocess.Popen  [new]
MasterZiv
Member

Откуда: Питер
Сообщений: 34697
maxkar,

есть еще пакет multiprocessing.
24 мар 17, 07:31    [20327998]     Ответить | Цитировать Сообщить модератору
 Re: [python] - тонкие отличия os.popen2 и subprocess.Popen  [new]
Vladimir Baskakov
Member

Откуда:
Сообщений: 2006
....... решено. os.popen2 открывал каналы, убирающие \r из потока. В отличие от subprocess.popen. искать, почему так, уже лень.

просто доработал цикл чтения ........
24 мар 17, 09:36    [20328267]     Ответить | Цитировать Сообщить модератору
 Re: [python] - тонкие отличия os.popen2 и subprocess.Popen  [new]
Vladimir Baskakov
Member

Откуда:
Сообщений: 2006
maxkar ,

universal_newlines=True

- да. наверное это оно. теперь буду знать, спасибо
24 мар 17, 09:39    [20328280]     Ответить | Цитировать Сообщить модератору
Все форумы / PHP, Perl, Python Ответить