2011-07-18 27 views
16

Tôi đang cố triển khai một cái gì đó tương tự như git log, sẽ chỉ trang đầu ra nếu nhật ký có độ dài nhất định. Nếu bạn không quen thuộc với git, tôi về cơ bản cố gắng để đạt được điều này:Đầu ra phân trang từ python

python some_script.py | less 

Với một số sự giúp đỡ từ việc thực hiện phân trang trong python2.6/pydoc.py, tôi đã có thể đưa ra với điều này:

import os 
text = '...some text...' 
pipe = os.popen('less', 'w') 
pipe.write(text) 
pipe.close() 

hoạt động tốt nhưng os.popen() không được dùng nữa. Tôi đã xem xét việc viết một tập tin tạm thời và gọi ít hơn với đường dẫn của nó, nhưng điều đó không có vẻ lý tưởng. Điều này có thể với subprocess không? Bất kỳ ý tưởng nào khác?

CHỈNH SỬA:

Vì vậy, tôi đã nhận được quy trình phụ. Tôi đã có thể để cho nó biến văn bản với Popen.communicate(text), nhưng kể từ khi tôi thực sự muốn chuyển hướng báo cáo in, tôi đã giải quyết về vấn đề này:

import os, sys, subprocess, tempfile 

    page = True 
    if page: 
     path = tempfile.mkstemp()[1] 
     tmp_file = open(path, 'a') 
     sys.stdout = tmp_file 
    print '...some text...' 
    if page: 
     tmp_file.flush() 
     tmp_file.close() 
     p = subprocess.Popen(['less', path], stdin=subprocess.PIPE) 
     p.communicate() 
     sys.stdout = sys.__stdout__  

Tất nhiên, tôi muốn kết thúc gói nó vào chức năng. Có ai nhìn thấy một vấn đề với điều đó không?

+0

Một vài lưu ý: (1) tên tệp tạm thời là duy nhất: chế độ mở phải là 'w', không phải 'a' (không thể nối thêm vào tệp). (2) Không cần phải 'close()' tệp trước khi đọc nó. (3) Không cần phải giao tiếp với quá trình máy nhắn tin (đơn giản là 'subprocess.call()' suffices). (4) Rõ ràng hơn là không làm xáo trộn toàn cầu như 'sys.stdout'; trừ khi bạn thực sự cần phải làm điều này (như nếu bạn muốn chuyển hướng đầu ra của tất cả các mô-đun con mà bạn sử dụng), bạn nên gọi một cách rõ ràng chức năng in đặc biệt. – EOL

+0

Đây là chủ đề tương tự với tốt đẹp và pithy Trả lời: http://stackoverflow.com/questions/37584717/how-to-write-python-script-with-man-page-like-out-put/ – user3019074

Trả lời

3

Sử dụng tiến trình con.Chọn thay thế.

http://docs.python.org/library/subprocess.html#subprocess-replacements

http://docs.python.org/library/subprocess.html#subprocess.Popen

Thậm chí còn có một lưu ý về điều này trong các tài liệu os.popen.

http://docs.python.org/library/os.html#os.popen

+0

Vâng, đó là điều đầu tiên tôi đã thử. Không thể làm cho nó hoạt động lúc đầu, nhưng bây giờ. Cảm ơn. – nren

+0

Chắc chắn. Tôi đã đưa nó cho bạn. Tôi đã hy vọng cho một số lời khuyên thực hiện chung hơn nếu bạn có bất kỳ - xem chỉnh sửa của tôi. – nren

+0

Chúc tôi có thể giúp bạn nhiều hơn nhưng tôi đang sử dụng Windows ngay bây giờ và không ai trong số này làm việc cho tôi, ngay cả khi cung cấp đường dẫn đầy đủ của MSYS của tôi cung cấp ít hơn. – agf

4

Đó là một ý tưởng tốt để được rõ ràng trong mã của bạn, do đó nó cho thấy rằng bạn sử dụng một chức năng in đặc biệt printc() thay vì một trong những tiêu chuẩn. Sử dụng subprocess.call() cũng đủ (bạn không cần máy móc ống). Hơn nữa, bạn có thể tiết kiệm một biến bằng cách không lưu trữ tên của tập tin tạm thời:

from __future__ import print_function 

import subprocess, tempfile 

page = True # For tests 

# Definition of a printc() function that prints to the correct output 
if page: 
    tmp_file = open(tempfile.mkstemp()[1], 'w') # No need to store the name in a specific variable 
    def printc(*largs, **kwargs): 
     if 'file' not in kwargs: # The code can still use the usual file argument of print() 
      kwargs['file'] = tmp_file # Forces the output to go to the temp file 
     print(*largs, **kwargs) 
else: 
    printc = print # Regular print 

# Main program: 

printc('...some text...', 'some more text', sep='/') # Python3 syntax 

# Paging of the current contents of the temp file: 
if page: 
    tmp_file.flush() # No need to close the file: you can keep printing to it 
    subprocess.call(['less', tmp_file.name]) # Simpler than a full Popen() 

Bằng cách này, bạn sẽ có được sự linh hoạt của print chức năng Python 3, với một mã mà rõ ràng cho thấy rằng bạn đang làm một số ưa thích công cụ in ấn. Điều này quy mô tốt hơn với các chương trình lớn hơn thay đổi biến "toàn cầu" sys.stdout ở một số vị trí trong mã của bạn.

+1

Cảm ơn lời khuyên! Tôi đã thêm tối ưu hóa của bạn. Tôi cần phải chuyển hướng đầu ra submodule, như bạn đã đề cập trong bình luận, do đó, nó có vẻ như tôi đang mắc kẹt với cách tiếp cận sys.stdout. Tôi đã đặt tất cả vào một lớp, vì vậy nó có thể được gọi với 'pager = Pager()' và 'pager.begin()'. – nren

28

Làm thế nào về điều này:

import pydoc 
text = '... some text ... ' 
pydoc.pager(text) 

này (vào hộp linux opensuse của tôi) gửi văn bản đến một máy nhắn tin ('ít' trong trường hợp của tôi), và hoạt động giống như kêu gọi "giúp đỡ (... lệnh python ...) "trong trình thông dịch Python.

+3

Trong khi tôi nghi ngờ rằng chức năng này sẽ không có sẵn trong tương lai, [nó không phải là tài liệu] (https://docs.python.org/3.5/library/pydoc.html), thật không may, vì vậy trong nguyên tắc nó không phải là đầy đủ đảm bảo rằng nó sẽ vẫn có sẵn. Tuy nhiên, vì nó tiện lợi như thế nào, tôi đoán rằng đây là một nguy cơ thường phải đáng giá. Hơn nữa, [source code] (https://hg.python.org/cpython/file/3.5/Lib/pydoc.py#l1406) có vẻ như nó có thể dễ dàng được sao chép. – EOL

+0

Nó làm hỏng đầu ra của tôi khi cố in một dữ liệu json được định dạng. –

2

Tôi không thích thực hiện các lệnh bên ngoài, vì vậy tôi đã viết pager bằng Python thuần túy. Nó vẫn còn có một vấn đề - đầu vào đường ống chỉ hoạt động cho Windows.

+0

Mô-đun máy nhắn tin không hoạt động với unicode: ( – MichaelR

+0

@MichaelR, vui lòng mở một báo cáo lỗi ở đây - https://bitbucket.org/techtonik/python-pager/issues để nó không bị mất. –

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