Так как Вы - удобные мечущие икру внешние процессы от своего кода, Вы могли использовать tee
самого. Я не знаю ни о каких системных вызовах Unix, которые делают точно, что tee
делает.
# Note this version was written circa Python 2.6, see below for
# an updated 3.3+-compatible version.
import subprocess, os, sys
# Unbuffer output (this ensures the output is in the correct order)
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
tee = subprocess.Popen(["tee", "log.txt"], stdin=subprocess.PIPE)
os.dup2(tee.stdin.fileno(), sys.stdout.fileno())
os.dup2(tee.stdin.fileno(), sys.stderr.fileno())
print "\nstdout"
print >>sys.stderr, "stderr"
os.spawnve("P_WAIT", "/bin/ls", ["/bin/ls"], {})
os.execve("/bin/ls", ["/bin/ls"], os.environ)
Вы могли также эмулировать tee
использование многопроцессорная обработка пакет (или использование обработка при использовании Python 2.5 или ранее).
Обновление
Вот является Python 3.3 +-compatible версией:
import subprocess, os, sys
tee = subprocess.Popen(["tee", "log.txt"], stdin=subprocess.PIPE)
# Cause tee's stdin to get a copy of our stdin/stdout (as well as that
# of any child processes we spawn)
os.dup2(tee.stdin.fileno(), sys.stdout.fileno())
os.dup2(tee.stdin.fileno(), sys.stderr.fileno())
# The flush flag is needed to guarantee these lines are written before
# the two spawned /bin/ls processes emit any output
print("\nstdout", flush=True)
print("stderr", file=sys.stderr, flush=True)
# These child processes' stdin/stdout are
os.spawnve("P_WAIT", "/bin/ls", ["/bin/ls"], {})
os.execve("/bin/ls", ["/bin/ls"], os.environ)
Это более или менее то, что вы хотите ...?
from pyparsing import Literal,Word,ZeroOrMore,Forward,nums,oneOf
def Syntax():
op = oneOf( '+ - / *')
lpar = Literal( '(' )
rpar = Literal( ')' )
num = Word(nums)
expr = Forward()
atom = num | ( lpar + expr + rpar )
expr << atom + ZeroOrMore( op + expr )
return expr
if __name__ == "__main__":
expr = Syntax()
def test(s):
results = expr.parseString( s )
print s,'->', results
test( "(9 + 3)" )
test( "(9 + 3) * (4 / 5)" )
излучает
(9 + 3) -> ['(', '9', '+', '3', ')']
(9 + 3) * (4 / 5) -> ['(', '9', '+', '3', ')', '*', '(', '4', '/', '5', ')']
? Это «закрепляет» рекурсию, отделяя «атом» (число или выражение в скобках) от «выражения» (один или несколько «атомов» с операторами между ними).
С такой грамматикой, как:
expr :: expr op expr
трудно работать, потому что рекурсия просто продолжает уходить влево.
Обычная арифметическая грамматика будет выглядеть примерно так:
expr :: mulxp | mulxp '+' expr
mulxp :: atom | atom '*' expr
atom :: Word(nums) | '(' + expr + ')'
По сути, вы никогда не получите S :: S
; Каждый раз, когда нетерминал появляется слева и справа от строки в грамматике, в середине должен быть какой-то литерал, чтобы синтаксический анализатор мог его обработать.
Ух ты, я думаю, пипарсинг действительно актуален! Спасибо, Алекс и Джон, что ответили на этот вопрос. Вы оба на высоте со своими ответами. Но позвольте мне добавить один-два комментария:
Если мы подавим символы открывающей и закрывающей скобок и сгруппируем заключенное в скобки выражение с помощью Group, pyparsing даст структурированный результат, который ближе к AST.
из pyparsing import Literal, Word, ZeroOrMore, Forward, nums, oneOf, Group
def Синтаксис ():
op = oneOf ('+ -')
lpar = Literal ('(') .suppress ()
rpar = Литерал (')') .suppress ()
num = Слово (числа)
expr = Вперед ()
атом = число | Группа (lpar + expr + rpar)
expr << атом + ZeroOrMore (op + атом)
return expr
если __name__ == "__main__":
expr = Синтаксис ()
def тест (ы):
results = expr.parseString (s)
print s, '->', результаты
тест ("(9 + 3)")
тест ("(9 + 3) * (4/5)")
Раздача:
(9 + 3) -> [['9', '+', '3']]
(9 + 3) * (4/5) -> [['9', '+', '3'], '*', ['4', '/', '5']]
В противном случае pyparsing - это просто токенизация, и вам нужно пройти по списку проанализированных токенов, чтобы найти вложенные выражения.
Поскольку op определен как просто oneOf ("+ - * /"), нет приоритета операции. В репозитории pyparsing есть примеры https://github.com/pyparsing/pyparsing/tree/master/examples ручного способа определения этого (fourFn.py) или более свежего подхода с использованием помощник infixNotation
(simpleArith.py). Опять же, у этого pyparsing больше ценности, чем просто токенизация.
Что касается OP, пожалуйста, ознакомьтесь с этими примерами, я думаю, они помогут продвинуть вас вперед в вашем проекте.
- Paul