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.stdin
chỉ 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 dup2
nế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 print
và input
. 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.stdin
và sys.stdout
theo 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 print
các cuộc gọi:
print[text]
#replaced with...
print[text, file=output_stream]
Tuy nhiên, input
khô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.fileno
và kiểm tra sys.stdin.encoding
và sys.stdin.errors
hơ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 stdin
và stdout
khô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 mock
mô-đ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.stdin
của Python, input
hàm của Python sẽ sử dụng nó thay vì đầu vào chuẩn. Nhưng hãy nhớ gán sys.stdin
lạ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.txt
và outputfile.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 io
mô-đun. Nó cung cấp io.StringIO
lớ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ẻ