Hướng dẫn dùng sys.stdin python

Vì vậy, bạn đã sử dụng "các hàm được tích hợp sẵn" của Python, có lẽ như thế này:

file_object = open['filename']
for something in file_object:
    some stuff here

Thao tác này đọc tệp bằng cách gọi một trình lặp trên đối tượng tệp sẽ trả về dòng tiếp theo từ tệp.

Thay vào đó, bạn có thể sử dụng:

file_object = open['filename']
lines = file_object.readlines[]

mà đọc các dòng từ vị trí tệp hiện tại vào một danh sách.

Bây giờ, sys.stdinchỉ là một đối tượng tệp khác, sẽ được Python mở trước khi chương trình của bạn bắt đầu. Những gì bạn làm với đối tượng tệp đó là tùy thuộc vào bạn, nhưng nó không thực sự khác biệt với bất kỳ đối tượng tệp nào khác, chỉ là bạn không cần một đối tượng tệp open.

for something in sys.stdin:
    some stuff here

sẽ lặp lại thông qua đầu vào chuẩn cho đến khi đạt đến phần cuối của tệp. Và điều này cũng vậy:

lines = sys.stdin.readlines[]

Câu hỏi đầu tiên của bạn thực sự là về các cách khác nhau để sử dụng một đối tượng tệp.

Thứ hai, nó được đọc từ đâu? Nó đang đọc từ bộ mô tả tệp 0 [không]. Trên Windows, nó là tệp xử lý 0 [không]. Bộ mô tả tệp / tay cầm 0 được kết nối với bảng điều khiển hoặc tty theo mặc định, do đó, trên thực tế, nó đang đọc từ bàn phím. Tuy nhiên, nó có thể được chuyển hướng , thường bằng một shell [như bash hoặc cmd.exe] bằng cách sử dụng cú pháp như sau:

myprog.py < input_file.txt 

Điều đó làm thay đổi bộ mô tả tệp bằng không để đọc tệp thay vì bàn phím. Trên UNIX hoặc Linux, điều này sử dụng lệnh gọi cơ bản dup2[]. Đọc tài liệu trình bao của bạn để biết thêm thông tin về chuyển hướng [hoặc có thể man dup2nếu bạn dũng cảm].

25 hữu ích 1 bình luận chia sẻ

Tôi muốn kiểm tra một số mã [python 3] sử dụng trực tiếp các hàm printinput. Theo tôi hiểu, cách dễ nhất để làm điều này là chèn phụ thuộc: sửa đổi mã để nó nhận các luồng đầu vào và đầu ra làm đối số, sử dụng sys.stdinsys.stdouttheo mặc định và chuyển vào các đối tượng giả trong quá trình thử nghiệm. Rõ ràng là phải làm gì với printcác cuộc gọi:

print[text]
#replaced with...
print[text, file=output_stream]

Tuy nhiên, inputkhông có đối số cho các luồng đầu vào và đầu ra. Đoạn mã sau có tái tạo chính xác hành vi của nó không?

text = input[prompt]
#replaced with...
print[prompt, file=output_stream, end='']
text = input_stream.readline[][:-1]

Tôi đã xem xét việc triển khai input, và nó thực hiện khá nhiều phép thuật, gọi sys.stdin.filenovà kiểm tra sys.stdin.encodingsys.stdin.errorshơn là gọi bất kỳ read*phương pháp nào - tôi không biết bắt đầu từ đâu với việc chế giễu chúng.

  • python
  • dependency-injection
  • python-3.x
  • mocking
  • stdin

3 hữu ích 4 bình luận 4.0k xem chia sẻ

answer

6

input[]chỉ phép thuật mà bạn đã đề cập khi stdinstdoutkhông bị thay đổi, bởi vì chỉ khi đó nó mới có thể sử dụng những thứ như thư viện dòng đọc. Nếu bạn thay thế chúng bằng một cái gì đó khác [tệp thực hoặc không], nó sẽ đi đến mã sau:

/* Fallback if we're not interactive */
if [promptarg != NULL] {
    if [PyFile_WriteObject[promptarg, fout, Py_PRINT_RAW] != 0]
         return NULL;
}
tmp = _PyObject_CallMethodId[fout, &PyId_flush, ""];
if [tmp == NULL]
    PyErr_Clear[];
else
    Py_DECREF[tmp];
return PyFile_GetLine[fin, -1];

Nơi PyFile_GetLine gọireadline phương thức. Như vậy việc chế nhạo sys.std*sẽ có tác dụng.

Bạn nên thực hiện việc này với try: finally:bộ xử lý ngữ cảnh hoặc mockmô-đun để kết quả đầu ra được khôi phục ngay cả khi mã bạn đang kiểm tra không thành công với các ngoại lệ:

from unittest.mock import patch
from io import StringIO

with patch["sys.stdin", StringIO["FOO"]], patch["sys.stdout", new_callable=StringIO] as mocked_out:
    x = input[]
    print["Read:", x]

assert mocked_out.getvalue[] == "Read: FOO\n"

6 hữu ích 0 bình luận chia sẻ

answer

5

Nếu bạn gán một đối tượng giống tệp cho hàm sys.stdincủa Python, inputhàm của Python sẽ sử dụng nó thay vì đầu vào chuẩn. Nhưng hãy nhớ gán sys.stdinlại cho đầu vào tiêu chuẩn sau khi bạn hoàn tất. Thủ thuật tương tự áp dụng cho sys.stdout. Bạn có thể làm điều gì đó như sau:

original_stdin = sys.stdin
sys.stdin = open['inputfile.txt', 'r']

original_stdout = sys.stdout
sys.stdout = open['outputfile.txt', 'w']

response = input['say hi: ']
print[response]

sys.stdin = original_stdin
sys.stdout = original_stdout

Hai dòng này

response = input['say hi: ']
print[response]

sẽ sử dụng các tệp được chỉ định [ inputfile.txtoutputfile.txt] thay vì đầu vào tiêu chuẩn và đầu ra tiêu chuẩn.

CẬP NHẬT: Nếu bạn không muốn xử lý các tệp vật lý, hãy xem iomô-đun. Nó cung cấp io.StringIOlớp cho phép bạn thực hiện các hoạt động dòng văn bản trong bộ nhớ.

original_stdin = sys.stdin
sys.stdin = io.StringIO['input string']

original_stdout = sys.stdout
sys.stdout = io.StringIO[]

response = input['say hi: ']
print[response]

output = sys.stdout.getvalue[]

sys.stdin = original_stdin
sys.stdout = original_stdout

print[output]

5 hữu ích 3 bình luận chia sẻ

Đăng nhập để trả lời câu hỏi

Có thể bạn quan tâm

Chủ Đề