2015-11-23 16 views
7

(Tôi nghĩ) Tôi biết cách đọc từ một đường ống. Ý tôi là các cuộc gọi trên bash như thế nàyTìm hiểu xem có đầu vào từ một đường ống hay không trong Python?

echo Bähm | ./script.py 

này Python3 kịch bản làm việc với điều đó.

#!/usr/bin/env python3 
import sys 

x = sys.stdin.read() 

if x: 
    print(x) 
else: 
    print('no pipe') 

sys.exit() 

Nhưng khi tôi chỉ đơn giản là làm điều này trên bash

./script.py 

có gì xảy ra bởi vì nó chờ đợi cho đầu vào.

Vì vậy, tôi muốn kiểm tra (khi bắt đầu tập lệnh) nếu có đầu vào từ đường ống hay không. Nhưng tôi không biết tại sao size hoặc len không hoạt động trên sys.stdin hoặc sys.stdin.buffer.

Có thể có sự khác biệt trong việc xử lý giữa phiên bản 2 và 3 của Python?

+0

Đây có phải là Python-3.x cụ thể không? Tôi sẽ đưa vào chỉnh sửa thẻ để được chấp thuận hoặc bị từ chối. –

+0

Tôi không biết gì về Python2. Ví dụ của tôi là Python3.Và thường có sự khác biệt có liên quan giữa chúng. Đó là lý do tại sao tôi cố gắng làm cho câu hỏi của mình càng cụ thể càng tốt. Và rất nhiều câu hỏi Python trên SO trộn lẫn mọi thứ giữa 2 và 3 và gây nhầm lẫn cho người đọc. – buhtz

Trả lời

3

có gì xảy ra bởi vì nó chờ đợi cho đầu vào

Và đó là hoàn toàn tốt. Bạn muốn sửa một cái gì đó mà không cần bất kỳ sửa chữa, và như là một sản phẩm phụ bạn đang thực sự tạo ra vấn đề.

Hãy tưởng tượng quy trình đường ống thực hiện một số phép tính nặng và do đó, cần một thời gian để tạo đầu ra. Bạn không thể kiểm tra tính sẵn sàng của dữ liệu trong tập lệnh python của bạn. Bạn không biết khi nào dữ liệu sẽ có sẵn. Bạn phải kiên nhẫn.

Vì vậy, tôi muốn kiểm tra (khi bắt đầu tập lệnh) nếu có đầu vào từ đường ống hay không.

Không. Nếu, vì một lý do nào đó, ứng dụng của bạn không có nghĩa là chạy với một tty (chờ đầu vào của người dùng), hãy kiểm tra điều đó.

sys.stdin.isatty() 

Chỉ kiểm tra tính khả dụng của dữ liệu nếu có hạn chế về thời gian khó: ví dụ: người dùng phải trả lời trong vòng 2 giây.

+0

Tác phẩm này cho các trường hợp của tôi. Nhưng tôi không chắc liệu tôi có hiểu khái niệm đằng sau nó đúng không. Có lẽ có những trường hợp nó không hoạt động như tôi mong đợi? – buhtz

+0

Không phải là tôi biết ... thậm chí kiểm tra tty có vẻ là một overkill, hãy thử bất kỳ công cụ tốt unix công dân, 'mèo',' sed', ... họ sẽ kiên nhẫn chờ đợi cho người dùng đầu vào. Kiểm tra tính sẵn sàng đầu vào OTOH, * sẽ * phá vỡ trừu tượng hộp đen trừu tượng hộp, bởi vì mong đợi đầu vào ngay lập tức là không thực tế. –

+0

Còn về 'less'? Bạn có thể nói 'less file.txt' hoặc' cat file.txt | ít hơn. Đó không phải là suy nghĩ giống như tôi muốn? – buhtz

0

Bạn có thể đặt tệp nhập đầu vào thành không bị chặn và bắt giữ IOError: [Errno 11] Resource temporarily unavailable khi không có gì được truyền.

import fcntl 
import os 
import sys 

# make stdin a non-blocking file 
fd = sys.stdin.fileno() 
fl = fcntl.fcntl(fd, fcntl.F_GETFL) 
fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) 

try: 
    print(sys.stdin.read()) 
except: 
    print('No input') 
+0

trừ1. Nghe có vẻ là một ý tưởng tồi tệ đối với tôi. Nếu quá trình đường ống chỉ cần một thời gian trước khi nó có thể tạo ra một số đầu ra? –

+0

@KarolyHorvath: Đó không phải là những gì buhtz yêu cầu. Anh ấy muốn biết liệu có đầu vào hay không. Mã của Cyrbil có lẽ là cách nền tảng chéo nhất để làm điều đó. Nếu bạn muốn đợi, hãy đặt mã của mình trong một vòng lặp với bộ đếm thời gian cho đến khi hết hạn hoặc đọc() trả về. – Harvey

+0

@Harvey: Tôi nghĩ anh ấy đã hỏi sai. http://xyproblem.info/ –

0

Bạn có thể sử dụng lựa chọn, nhưng nó không hoạt động trên Windows:

import sys 
import select 

# Input: zero or more file-like objects 
# Returns: list of objects that can be read 
def can_read_files(*args): 
    return select.select(args, [], [], 0.0)[0] 

if can_read_files(sys.stdin): 
    print(sys.stdin.read()) 
else: 
    print('No input') 

Đối với chúng tôi nó inline:

if select.select([sys.stdin], [], [], 0.0)[0]: 
    ... 
2

Ngoài ra để @ câu trả lời Cyrbil nếu bạn thực sự cần phải biết nếu đầu vào được nhập vào, bạn có thể sử dụng isatty:

from sys import stdin 
from os import isatty 

is_pipe = not isatty(stdin.fileno()) 
+1

Tôi đã không mang lại giải pháp này bởi vì tôi đã có một số hành vi bất ngờ với 'stdin.isatty()' nhưng với 'os.isatty()' điều này dường như làm việc tốt. – Cyrbil

+0

@Cyrbil, tôi không biết rằng bạn có thể "hỏi" stdin trực tiếp nếu đó là TTY. Cảm ơn bạn về thông tin! Tôi không thể nói những gì là khác nhau. Có lẽ một số kỳ quặc với một PTY? – kay

+0

Có vẻ như 'stdin.isatty()' luôn trả về 'True'. Tôi không thể sản xuất một trường hợp mà nó trả về cho tôi False ... Vì vậy, 'os.isatty()' là cách tốt nhất. – Cyrbil

Các vấn đề liên quan