මුද්‍රණ ශ්‍රිතයේ ප්‍රතිදානය ගලා යන්නේ කෙසේද?


1246

පයිතන්ගේ මුද්‍රණ කාර්යය තිරයට ප්‍රතිදානය කිරීමට මා බල කරන්නේ කෙසේද?

මෙය ප්‍රතිදාන බෆරින් අක්‍රීය කිරීමේ අනුපිටපතක් නොවේ - සම්බන්ධිත ප්‍රශ්නය අනාරක්ෂිත ප්‍රතිදානය සඳහා උත්සාහ කරන අතර මෙය වඩාත් සාමාන්‍ය වේ. එම ප්‍රශ්නයේ ඉහළම පිළිතුරු මේ සඳහා බලවත් හෝ සම්බන්ධ වී ඇත (ඒවා මේ සඳහා හොඳ පිළිතුරු නොවේ), මෙම ප්‍රශ්නය ගූගල් හි සාපේක්ෂ නවකයෙකු විසින් සොයාගත හැකිය.

Answers:


1466

පයිතන් 3 printහි විකල්ප flushතර්කයක් ගත හැකිය

print("Hello world!", flush=True)

පයිතන් 2 හි ඔබට කළ යුතුව ඇත

import sys
sys.stdout.flush()

ඇමතුමෙන් පසු print. පෙරනිමියෙන්, printමුද්‍රණය කරයි sys.stdout( ගොනු වස්තු පිළිබඳ වැඩි විස්තර සඳහා ප්‍රලේඛනය බලන්න ).


353

ධාවනය වන විට python -h, මට විධාන රේඛා විකල්පයක් පෙනේ :

-u: නොකැඩූ ද්විමය stdout සහ stderr; PYTHONUNBUFFERED = x '-u' හා සම්බන්ධ අභ්‍යන්තර බෆරින් පිළිබඳ විස්තර සඳහා man පිටුව බලන්න.

මෙන්න අදාළ ලේඛනය .


324

පයිතන් 3.3 සිට, සාමාන්‍ය print()ක්‍රියාකාරිත්වය භාවිතයෙන් තොරව ගලා යාමට ඔබට බල කළ හැකිය sys.stdout.flush(); "ෆ්ලෂ්" යතුරු පද තර්කය සත්‍ය ලෙස සකසන්න. සිට ලේඛගතකිරීම :

print (* object, sep = '', end = '\ n', file = sys.stdout, flush = False)

ධාරා ගොනුවට වස්තු මුද්‍රණය කරන්න, sep මගින් වෙන් කොට අවසානය. sep, end සහ file, තිබේ නම්, එය මූලික වචන තර්ක ලෙස ලබා දිය යුතුය.

සියලුම මූල පද නොවන තර්ක str () වැනි නූල් බවට පරිවර්තනය කර ප්‍රවාහයට ලියා, sep මගින් වෙන් කොට අවසානය දක්වා. සේප් සහ අවසානය යන දෙකම නූල් විය යුතුය; ඒවා කිසිවක් විය නොහැක, එයින් අදහස් කරන්නේ පෙරනිමි අගයන් භාවිතා කිරීමයි. කිසිදු වස්තුවක් ලබා දී නොමැති නම්, මුද්‍රණය () අවසානය ලියනු ඇත.

ගොනු තර්කය ලිවීමේ (නූල්) ක්‍රමයක් සහිත වස්තුවක් විය යුතුය; එය නොමැති නම් හෝ කිසිවක් නොමැති නම්, sys.stdout භාවිතා කරනු ඇත. ප්‍රතිදානය ස්වාරක්ෂකද යන්න සාමාන්‍යයෙන් තීරණය වන්නේ ගොනුවෙනි, නමුත් ෆ්ලෂ් යතුරු පද තර්කය සත්‍ය නම්, ධාරාව බලහත්කාරයෙන් ගලා යයි.


203

පයිතන් මුද්‍රණයේ ප්‍රතිදානය ගලා යන්නේ කෙසේද?

මෙය කිරීමට ක්‍රම පහක් මම යෝජනා කරමි:

  • පයිතන් 3 හි, අමතන්න print(..., flush=True)(පයිතන් 2 හි මුද්‍රණ ශ්‍රිතයේ ෆ්ලෂ් තර්කය නොමැත, මුද්‍රණ ප්‍රකාශය සඳහා ප්‍රතිසමයක් නොමැත).
  • file.flush()ප්‍රතිදාන ගොනුව අමතන්න (මෙය සිදු කිරීම සඳහා අපට පයිතන් 2 හි මුද්‍රණ කාර්යය ඔතා ගත හැකිය), උදාහරණයක් ලෙසsys.stdout
  • මොඩියුලයේ සෑම මුද්‍රණ ශ්‍රිත ඇමතුමකටම අර්ධ ශ්‍රිතයක් සහිත මෙය
    print = partial(print, flush=True)ගෝලීය මොඩියුලයට යොදන්න .
  • -uපරිවර්තක විධානයට ලබා දුන් ධජයක් ( ) සමඟ ක්‍රියාවලියට මෙය යොදන්න
  • ඔබගේ පරිසරයේ ඇති සෑම පයිතන් ක්‍රියාවලියකටම මෙය යොදන්න PYTHONUNBUFFERED=TRUE(මෙය අහෝසි කිරීමට විචල්‍යය සකසන්න).

පයිතන් 3.3+

පයිතන් 3.3 හෝ ඊට වැඩි භාවිතා කිරීමෙන් ඔබට ශ්‍රිතයට flush=Trueමූල පදයක් ලෙස සැපයිය හැකිය print:

print('foo', flush=True) 

පයිතන් 2 (හෝ <3.3)

ඔවුන් flushතර්කය පයිතන් 2.7 වෙත ආපසු යැව්වේ නැත. එබැවින් ඔබ පයිතන් 2 (හෝ 3.3 ට වඩා අඩු) භාවිතා කරන්නේ නම් සහ 2 සහ 3 යන දෙකටම අනුකූල කේත අවශ්‍ය නම්, මම පහත දැක්වෙන අනුකූලතා කේතය යෝජනා කරමි. ( __future__ආනයනය ඔබගේ මොඩියුලයේ ඉහළින්ම තිබිය යුතු බව සලකන්න ):

from __future__ import print_function
import sys

if sys.version_info[:2] < (3, 3):
    old_print = print
    def print(*args, **kwargs):
        flush = kwargs.pop('flush', False)
        old_print(*args, **kwargs)
        if flush:
            file = kwargs.get('file', sys.stdout)
            # Why might file=None? IDK, but it works for print(i, file=None)
            file.flush() if file is not None else sys.stdout.flush()

ඉහත අනුකූලතා කේතය බොහෝ භාවිතයන් ආවරණය කරනු ඇත, නමුත් වඩාත් ගැඹුරු ප්‍රතිකාරයක් සඳහා sixමොඩියුලය බලන්න .

විකල්පයක් ලෙස, ඔබට file.flush()මුද්‍රණයෙන් පසු ඇමතිය හැකිය , උදාහරණයක් ලෙස, පයිතන් 2 හි මුද්‍රණ ප්‍රකාශය සමඟ:

import sys
print 'delayed output'
sys.stdout.flush()

පෙරනිමිය එක් මොඩියුලයකට වෙනස් කිරීම flush=True

මොඩියුලයක ගෝලීය විෂය පථය මත functools.partial භාවිතා කිරීමෙන් මුද්‍රණ කාර්යයේ පෙරනිමිය ඔබට වෙනස් කළ හැකිය:

import functools
print = functools.partial(print, flush=True)

ඔබ අපගේ නව අර්ධ ක්‍රියාකාරිත්වය දෙස බැලුවහොත්, අවම වශයෙන් පයිතන් 3 හි:

>>> print = functools.partial(print, flush=True)
>>> print
functools.partial(<built-in function print>, flush=True)

එය සාමාන්‍ය ආකාරයටම ක්‍රියාත්මක වන බව අපට පෙනේ:

>>> print('foo')
foo

අපට නව පෙරනිමිය අභිබවා යා හැකිය:

>>> print('foo', flush=False)
foo

නැවත වරක් සටහන් කරන්න, මෙය වර්තමාන ගෝලීය විෂය පථය පමණක් වෙනස් කරයි, මන්ද වර්තමාන ගෝලීය විෂය පථයේ මුද්‍රණ නාමය බිල්ඩින් printශ්‍රිතය යටපත් කරනු ඇත (හෝ පයිතන් 2 හි එකක් භාවිතා කරන්නේ නම්, එම ගෝලීය විෂය පථය තුළ අනුකූලතා ශ්‍රිතය නොසලකා හැරීම ).

මොඩියුලයේ ගෝලීය විෂය පථය වෙනුවට ශ්‍රිතයක් තුළ මෙය කිරීමට ඔබට අවශ්‍ය නම්, ඔබ එයට වෙනත් නමක් දිය යුතුය, උදා:

def foo():
    printf = functools.partial(print, flush=True)
    printf('print stuff like this')

ඔබ එය ශ්‍රිතයක ගෝලීය යැයි ප්‍රකාශ කරන්නේ නම්, ඔබ එය මොඩියුලයේ ගෝලීය නාම අවකාශය මත වෙනස් කරයි, එබැවින් ඔබ එය ගෝලීය නාම අවකාශයට දැමිය යුතුය, එම නිශ්චිත හැසිරීම හරියටම ඔබට අවශ්‍ය දේ නොවේ නම්.

ක්‍රියාවලිය සඳහා පෙරනිමිය වෙනස් කිරීම

මම හිතන්නේ මෙහි ඇති හොඳම විකල්පය වන්නේ -uධජය භාවිතා කර නොවරදින ප්‍රතිදානය ලබා ගැනීමයි.

$ python -u script.py

හෝ

$ python -um package.module

සිට ලේඛන :

Stdin, stdout සහ stderr මුළුමනින්ම නොසැලකිලිමත් වීමට බල කරන්න. එය වැදගත් වන පද්ධති වලදී, stdin, stdout සහ stderr ද්විමය ප්‍රකාරයට දමන්න.

මෙම විකල්පයට බලපෑම් නොකරන file.readlines () සහ ගොනු වස්තු (sys.stdin හි පේළිය සඳහා) අභ්‍යන්තර බෆරින් ඇති බව සලකන්න. මේ සඳහා වැඩ කිරීමට, ඔබට 1: loop තුළ file.readline () භාවිතා කිරීමට අවශ්‍ය වනු ඇත.

ෂෙල් මෙහෙයුම් පරිසරය සඳහා පෙරනිමිය වෙනස් කිරීම

ඔබ පරිසර විචල්‍යය නොවරදින නූලකට සකසන්නේ නම් පරිසරයේ හෝ පරිසරයේ ඇති සියලුම පයිතන් ක්‍රියාවලීන් සඳහා ඔබට මෙම හැසිරීම ලබා ගත හැකිය:

උදා: ලිනක්ස් හෝ ඕඑස්එක්ස් වලින්:

$ export PYTHONUNBUFFERED=TRUE

හෝ වින්ඩෝස්:

C:\SET PYTHONUNBUFFERED=TRUE

සිට ලේඛන :

පයිතොනන්බුෆර්ඩ්

මෙය හිස් නොවන නූලකට සකසා ඇත්නම් එය -u විකල්පය නියම කිරීමට සමාන වේ.


අතිරේක

පයිතන් 2.7.12 වෙතින් මුද්‍රණ කාර්යය සඳහා උපකාර මෙන්න - තර්කයක් නොමැති බව සලකන්න flush:

>>> from __future__ import print_function
>>> help(print)
print(...)
    print(value, ..., sep=' ', end='\n', file=sys.stdout)
    
    Prints the values to a stream, or to sys.stdout by default.
    Optional keyword arguments:
    file: a file-like object (stream); defaults to the current sys.stdout.
    sep:  string inserted between values, default a space.
    end:  string appended after the last value, default a newline.

පහළ පයිතන් අනුවාද වලින් කුතුහලයෙන් සංක්‍රමණය වීම සඳහා: __future__අනුවාදයට ඇතුළත් නොවන්නේ flush“ෆ්ලෂ් තර්කය පයිතන් 3.3 හි එකතු කර ඇති හෙයිනි (මුද්‍රණයෙන් පසු () අනාගත ආනයනයක් හරහා 2.7 වෙත ආපසු යවන ලදි)” bugs.python.org/issue28458
ඔලිවර්

69

මෙම බ්ලොග් අඩවියේ යෝජනා කර ඇති පරිදි යමෙකුට sys.stdoutඅනාරක්ෂිත ආකාරයකින් නැවත විවෘත කළ හැකිය :

sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)

එක් එක් stdout.writeහා printමෙහෙයුම් ස්වයංක්රීයව පසුව සිරිල් වෙව්ලන්නට වනු ඇත.


2
පයිතන් 2.7 හි උබුන්ටු 12.04 හි මෙය මට ලබා දෙයිUnsupportedOperation: IOStream has no fileno.
ඩ්‍රෙවිකෝ

3
අපොයි, පයිතන් 3 සොයා ගත්තා. මෙම කේතය ක්‍රියාත්මක කිරීමට එය මට ඉඩ නොදේ!
EKons

මම මේ මෝඩකම නිසා ව්‍යාකූල වී සිටිමි. ඔබ මෙය කළ පසු, ගොනුවට සමාන වස්තූන් දෙකක් (මුල් sys.stdout සහ නව sys.stdout) දෙදෙනාම සිතන්නේ ඔවුන් ගොනු ගොනුව "අයිති" යැයි සිතනවාද? ඒක නරකයි නේද?
දොන් හැච්


36

-uවිධාන රේඛා ස්විචය භාවිතා කිරීම ක්‍රියා කරයි, නමුත් එය ටිකක් අවුල් සහගතය. -uවිකල්පයක් නොමැතිව පරිශීලකයා ස්ක්‍රිප්ටය ආයාචනා කළහොත් වැඩසටහන වැරදි ලෙස හැසිරෙනු ඇතැයි එයින් අදහස් වේ. මම සාමාන්‍යයෙන් stdoutමේ වගේ චාරිත්‍රයක් භාවිතා කරනවා:

class flushfile:
  def __init__(self, f):
    self.f = f

  def write(self, x):
    self.f.write(x)
    self.f.flush()

import sys
sys.stdout = flushfile(sys.stdout)

... දැන් ඔබගේ සියලුම printඇමතුම් ( sys.stdoutව්‍යංගයෙන් භාවිතා කරන ) ස්වයංක්‍රීයව flushසංස්කරණය වේ.


4
ගොනුවෙන් උරුම නොවී පසුව එකතු කිරීමෙන් stdout වෙත පැවරීම මම නිර්දේශ කරමි. def __getattr__(self,name): return object.__getattribute__(self.f, name)
deadthreetimes

2
Ieddiedthreetimes විසින් අදහස් දැක්වීමෙන් තොරව, මට "ValueError: සංවෘත ගොනුවේ I / O මෙහෙයුම" ලැබේ
blueFast

19

අනාරක්ෂිත ගොනුවක් භාවිතා කිරීමට උත්සාහ නොකරන්නේ ඇයි?

f = open('xyz.log', 'a', 0)

හෝ

sys.stdout = open('out.log', 'a', 0)

1
ඔහුට අනවශ්‍ය ගොනුවක් සෑදීමට අවශ්‍ය නැත; ඔහුට අවශ්‍ය වන්නේ දැනට පවතින stdout (කොන්සෝලය, පර්යන්තය හෝ වෙනත් දෙයකට හරවා යවනු ලැබේ: මෙය වෙනස් නොකළ යුතුය) නිරුපද්‍රිතව.
blueFast

13

ඩෑන් ගේ අදහස එතරම් සාර්ථක නොවේ:

#!/usr/bin/env python
class flushfile(file):
    def __init__(self, f):
        self.f = f
    def write(self, x):
        self.f.write(x)
        self.f.flush()

import sys
sys.stdout = flushfile(sys.stdout)

print "foo"

ප්රතිඵලය:

Traceback (most recent call last):
  File "./passpersist.py", line 12, in <module>
    print "foo"
ValueError: I/O operation on closed file

ගැටලුව වන්නේ එය ලිපිගොනු පන්තියෙන් උරුම වීමයි, එය ඇත්ත වශයෙන්ම අවශ්‍ය නොවේ. Sys.stdout සඳහා වන ලියකියවිලි වලට අනුව:

stdout සහ stderr ගොනු ගොනු වස්තු සෑදිය යුතු නොවේ: ඕනෑම වස්තුවකට ලිවීමේ () ක්‍රමයක් ඇති තාක් කල් එය පිළිගත හැකිය.

ඉතින් වෙනස් වෙනවා

class flushfile(file):

වෙත

class flushfile(object):

එය හොඳින් ක්‍රියාත්මක කරයි.


17
ඡන්දය
නොදෙන

9

මෙන්න මගේ අනුවාදය, එය ලිවීම් () සහ ෆයිල්නෝ () ද සපයයි:

class FlushFile(object):
    def __init__(self, fd):
        self.fd = fd

    def write(self, x):
        ret = self.fd.write(x)
        self.fd.flush()
        return ret

    def writelines(self, lines):
        ret = self.writelines(lines)
        self.fd.flush()
        return ret

    def flush(self):
        return self.fd.flush

    def close(self):
        return self.fd.close()

    def fileno(self):
        return self.fd.fileno()

සුපිරි විසඳුම. එය ක්රියා කරයි. පයිතන් 3.4.0 හි පරීක්ෂා කර ඇත. ව්‍යුත්පන්න වූ අනෙක් අනුවාද සමඟ file, මට දෝෂයක් ඇතිවේ. fileපන්තියක් නැත .
කොලින් ඩී බෙනට්

6

පයිතන් 3 හි පෙරනිමි සැකසුම සමඟ මුද්‍රණ ශ්‍රිතය නැවත ලිවිය හැකිය flush = True

def print(*objects, sep=' ', end='\n', file=sys.stdout, flush=True):
    __builtins__.print(*objects, sep=sep, end=end, file=file, flush=flush)

2
අනෙක් සියලුම උසස් තත්ත්වයේ ප්‍රතිචාර වලට අනුව මෙම පිළිතුර සුළු ආලෝකයක් සේ පෙනේ. ඔබට එයට තව ටිකක් එකතු කිරීමට අවශ්‍ය විය හැකිය.
අර්ධ සළකුණු සහ ඩක් ටේප්

6

පයිතන් 3.4 හි මම මේ ආකාරයට කළා:

'''To write to screen in real-time'''
message = lambda x: print(x, flush=True, end="")
message('I am flushing out now...')

2

ෆ්ලෂ් විකල්පය ක්‍රියාත්මක වන්නේ කෙසේදැයි තේරුම් ගැනීමට මම මුලින්ම වෙහෙසට පත් වීමි. මට 'පැටවීමේ සංදර්ශකයක්' කිරීමට අවශ්‍ය වූ අතර මම සොයාගත් විසඳුම මෙන්න:

for i in range(100000):
    print('{:s}\r'.format(''), end='', flush=True)
    print('Loading index: {:d}/100000'.format(i+1), end='')

පළමු පේළිය පෙර මුද්‍රණය විහිදුවන අතර දෙවන පේළිය නව යාවත්කාලීන පණිවිඩයක් මුද්‍රණය කරයි. එක් පේළියේ වාක්‍ය ඛණ්ඩයක් මෙහි තිබේදැයි මම නොදනිමි.

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.