명명된 파이프에서 stdin 가져오기

명명된 파이프에서 stdin 가져오기

내가 원하는 것은 터미널 창에서 Python을 실행하고 명명된 파이프에서 표준 입력을 리디렉션하는 것입니다. 그런 다음 다른 터미널의 명명된 파이프에 쓰고 Python에서 명령을 실행합니다.

터미널 1:

mkfifo p1
python < p1

NO2. 터미널:

echo -n "print \"Hello World\"" > p1

무슨 일이 일어나는가 - 파이썬이 인쇄 Hello World하고 종료됩니다. 내가 원하는 것은 Python을 계속 실행하여 다음 명령을 받아들이는 것입니다. 쉘에서 이 작업을 어떻게 수행합니까?

답변1

당신은해야합니다

  • 표준 입력이 터미널이 아니더라도 Python을 대화형으로 실행하려면 다음을 사용하십시오.python -i
  • 파이프의 쓰기 끝을 열어 두십시오. 그렇지 않으면 Python이 EOF를 감지하고 종료됩니다.

그래서:

python -i < p1

그리고 다른 곳에서는:

# open p1 on fd 3 of the shell process¹ for instance so stdout is
# left untouched in case you still want to write messages there.
exec 3> p1

# write something on fd 3. For instance with ksh/zsh's print
# builtin:
print -u3 '1j*1j'

# or for commands such as echo that can only print things
# on stdout (fd 1), duplicate that fd 3 to their fd 1:
echo '1j*1j' >&3 # short for 1>&3

# after echo (a builtin² in virtually all shells) returns, fd 1
# is restored to what it was before, but fd 3 remains open on
# the writing end of the pipe, so python still doesn't see EOF
# there.

echo normal message on stdout
echo 1+1 >&3 # more instructions for python
...
# and when done, close that file descriptor so python sees the EOF
# (assuming that fd 3 was the only file descriptor left open on
# the writing end of that pipe):
exec 3>&-

exec특히 스크립트에서는 3를 사용하여 fd를 수동으로 열고 닫는 대신 전체 명령 그룹을 리디렉션할 수 있습니다 .

{
  echo ... >&3
  ...
  ...
} 3> p1

¹ fd 3은 하위 프로세스 및 (ksh93에 close-on-exec 플래그가 설정된 경우 제외) 해당 프로세스에서 실행되는 다른 명령(있는 경우)에 의해 상속됩니다.

² 물론 이는 내장되지 않은 명령에도 적용됩니다. 내장되지 않은 프로그램의 경우 명령을 실행하기 위해 분기된 하위 프로세스에서만 리디렉션이 수행되므로 쉘은 fd 1을 저장하고 복원할 필요가 없습니다. 이 작업을 자동으로 수행하는 ksh93 이외의 외부 명령의 경우 실제로 fd 3을 꺼서 누출되지 않고 결국 백그라운드 프로세스가 생성될 수 있습니다( cmd >&3 3>&-).

³ 이 경우 ksh93은 fd 3에 close-on-exec 플래그를 설정하지 않습니다.

답변2

이를 사용하여 tail -f쓰기 후에 fifo를 열어 둘 수 있습니다.echo

tail -n1 -f p1 | python

이것이 작동하는 이유

python에서 읽기 p1파일의 끝에 도달하면 읽기가 중지됩니다. 이는 파일이 명명된 파이프인 경우에도 파일 읽기에 대한 일반적인 동작입니다. (follow) 플래그 tail가 있는 파일은 -f파일 끝에 도달한 후에도 계속 읽습니다.

답변3

전체 프로그램을 한 번에 보내야 합니다.

run을 호출하면 python < p1쉘은 Python을 호출하기 전에 입력을 기다립니다. 즉, Python은 실행을 시작하지도 않습니다.별말씀을요전체 데이터 스트림이 셸에서 읽힐 때까지 전체가 python.

대신 실행하더라도 python -u p1(즉, 버퍼링되지 않고 file 에서 읽는 경우 p1) python파일을 실행하기 전에 전체 파일을 읽으려는 시도가 이루어집니다.

이 실험을 시도해 보세요.

터미널 1:

mkfifo p1
python < p1

NO2. 터미널:

cat > p1
print "Hello World"
print "Hello World"

여러 줄을 보낼 수 있지만 1학기의 Python은 아무 작업도 수행하지 않는다는 것을 알 수 있습니다. 이제 ctrl+를 누르세요 D. 전체 프로그램이 즉시 실행됩니다.

요약하자면, Python이 파이프에서 데이터를 읽도록 하려면 전체 프로그램을 보내야 합니다. 이런 식으로 Python을 대화식으로 사용할 수 없습니다.

답변4

또 다른 해결책이 있습니다. 터미널 1:

alec@MacBook-Air ~/hello $ rm -f my.fifo; mkfifo my.fifo 
alec@MacBook-Air ~/hello $ cat my.fifo 
command1
command2
...
alec@MacBook-Air ~/hello $ 

NO2. 터미널:

alec@MacBook-Air ~/hello $ cat > my.fifo 
command1
command2
...
alec@MacBook-Air ~/hello $ 

터미널 2에 명령을 입력하고 터미널 1에 해당 명령이 나타나는지 확인합니다. 예를 들어 터미널 1의 출력을 다른 프로세스로 파이프할 수 있습니다 cat my.fifo | node .... 완료되면 stdinCtrl-D를 사용하여 터미널 2를 닫습니다. my.fifo그러면 닫히고 cat터미널 1의 명령이 종료됩니다.

관련 정보