Tek satırda dinamik olarak yazdırma


306

İfadeler arasında yeni satırlar görmeden standart çıktı veren birkaç ifade yapmak istiyorum.

Özellikle, varsayalım:

for item in range(1,100):
    print item

Sonuç:

1
2
3
4
.
.
.

Bunun yerine şöyle görünmesini sağlayın:

1 2 3 4 5 ...

Daha da iyisi, tek sayıyı üzerine yazdırmak mümkün son sayının mü, bu yüzden ekranda aynı anda sadece bir sayı var mı?


Yanıtlar:


482

Şununla print itemdeğiştir:

  • print item, Python 2.7 içinde
  • print(item, end=" ") Python 3'te

Verileri dinamik olarak yazdırmak istiyorsanız aşağıdaki sözdizimini kullanın:

  • print(item, sep=' ', end='', flush=True) Python 3'te

Gönderen http://docs.python.org/reference/simple_stmts.html#print :> A '\n'karakteri sürece, sonunda yazılır printaçıklamada uçları virgülle. Bu ifade yalnızca anahtar kelimeyi içeriyorsa tek işlemdir print.
ewall

5
FYI: print (item, end = "") Python2.7'de dosyanın üstüne ' gelecekteki import print_function'dan' eklenerek kullanılabilir .
Hec

2
Ancak maalesef flushile çalışmıyor from __future__ import print_function.
Timmmm

Yapmak olsaydı @ewall print(item, end=", ")bunu daha sonra da ekler ,ekleyerek engellemek nasıl yapılacağını son öğeye ,son öğeye
MarcoBianchi

@SamirTendulkar Orijinal soru gibi bir for-loop kullanıyorsanız, listedeki son öğeyi farklı şekilde ele almak için özel bir durum oluşturabilirsiniz ...
ewall

156

Bu arada ...... Nasıl bir yerde mi yazdırmak böylece her zaman yenilemek nasıl sadece numarasını değiştirmek.

Genel olarak bunu yapmanın yolu terminal kontrol kodlarıdır . Bu, sadece tek bir özel karaktere ihtiyacınız olan özellikle basit bir durumdur: '\r'Python'da (ve diğer birçok dilde) yazılmış U + 000D CARRIAGE RETURN . Kodunuza dayalı tam bir örnek:

from sys import stdout
from time import sleep
for i in range(1,20):
    stdout.write("\r%d" % i)
    stdout.flush()
    sleep(1)
stdout.write("\n") # move the cursor to the next line

Bu konuda şaşırtıcı olabilecek bazı şeyler:

  • \rProgram çalışırken, imleç her zaman sayıdan sonra olacak, böylece dize başında gider. Bu sadece kozmetik değil: bazı terminal emülatörleri başka şekilde yaparsanız çok karışık olurlar.
  • Son satırı eklemezseniz, program sona erdikten sonra kabuğunuz komut istemini sayının üstüne yazdıracaktır.
  • stdout.flushBazı sistemlerde gereklidir, yoksa herhangi bir çıktı almazsınız. Diğer sistemler gerektirmeyebilir, ancak herhangi bir zarar vermez.

Bunun işe yaramadığını fark ederseniz, şüphelenmeniz gereken ilk şey terminal emülatörünüzün hatalı olmasıdır. Vttest programı bunu test yardımcı olabilir.

Sen yerini alabilecek stdout.writebir ile printaçıklamaya ama karıştırmak için tercih printdosya nesnelerin doğrudan kullanımı ile.


Ne meen flush () işlevi? Çünkü bu işlev olmadan benim için çalışıyor!
Pol

1
Normalde, Python'un dosya nesneleri veri biriktirir, böylece büyük parçalar halinde işletim sistemine gönderebilirler. Genellikle diskteki dosyalara erişmek istediğiniz budur, ancak bu tür bir görevi engeller. flush()bir dosyayı şu anda işletim sistemine ne varsa göndermeye zorlar. Bu olmadan sizin için çalıştığına şaşırdım - ekleyene kadar benim için işe yaramadı.
zwol

1
@ user1995839 İmleci gizlemek için kontrol kodları vardır, ancak ncursesbunu yapacaksanız bunu kullanmanızı şiddetle tavsiye ederim .
zwol

1
sys.stdout.flush()Benim üzerinde mendatory edilebilir görülüyor FreebsdilePython 2.7
Hakim

1
Satır başı dönüşünün Python REPL içinde (en azından benim için Ubuntu'da) düzgün çalışmadığını unutmayın; bunların herhangi birinin çalışması için yalnızca bir REPL komutu çalıştırmakla kalmayan bir komut dosyası yürütmeniz gerekir.
Mark Amery

50

print item,Yazdırma ifadesini satır sonunu atlatmak için kullanın .

Python 3'te öyle print(item, end=" ").

Her numaranın aynı yerde görüntülenmesini istiyorsanız, örneğin (Python 2.7) kullanın:

to = 20
digits = len(str(to - 1))
delete = "\b" * (digits + 1)
for i in range(to):
    print "{0}{1:{2}}".format(delete, i, digits),

Python 3'te biraz daha karmaşık; burada yıkama yapmanız gerekir sys.stdoutveya döngü bitene kadar hiçbir şey yazdırmaz:

import sys
to = 20
digits = len(str(to - 1))
delete = "\b" * (digits)
for i in range(to):
   print("{0}{1:{2}}".format(delete, i, digits), end="")
   sys.stdout.flush()

Aslında, çözümünüz her seferinde aynı sayıda arka alan yazdıracak gibi görünüyor. Yani, eğer 20 ise, rakamları basarken fazladan bir geri basacaktır 1..9. Döngü içindeki rakamları hesaplayıp i değerinin tabanına almamalısınız?
Adam Crossland

Numarayı haklı gösterir ve her zaman her şeyi siler. Bunu yapmanın daha hızlı olup olmadığını veya her yinelemede şu anda kaç basamakın silineceğini hesaplamak için test yapmadım.
Tim Pietzcker

Veya, basamak sayısı değiştiğinde hesaba katmak için bunu önceki i değerinden temel alın.
Adam Crossland

Ah, evet, doğru gerekçeye fazla baktım. Güzel çözüm.
Adam Crossland

Kulağa oldukça karmaşık geliyor. Kodumu bir yıl sonra bakmak zorunda kalırdım, muhtemelen orada ne yapmıştı anlamıyorum. (2007'de yazdığım bir programı okumak zorunda kaldım - Python'a yazdığım için çok mutluyum.)
Tim Pietzcker

16

Diğer örnekler gibi
ben de benzer bir yaklaşım kullanıyorum ama son çıktı uzunluğunu hesaplamak için zaman harcamak yerine,

Sadece satır başına geri ANSI kodu kaçar kullanın ve sonra geçerli durum çıktımı yazdırmadan önce tüm satır temizlemek.

import sys

class Printer():
    """Print things to stdout on one line dynamically"""
    def __init__(self,data):
        sys.stdout.write("\r\x1b[K"+data.__str__())
        sys.stdout.flush()

Yineleme döngünüzde kullanmak için sadece şöyle bir şey çağırırsınız:

x = 1
for f in fileList:
    ProcessFile(f)
    output = "File number %d completed." % x
    Printer(output)
    x += 1   

Daha fazlasını burada görün


14

Her yinelemede yeni satır yerine boşluk yazdırmak için yazdırma ifadenize bir virgül ekleyebilirsiniz:

print item,

Alternatif olarak, Python 2.6 veya üstünü kullanıyorsanız, yazdırılan her öğenin sonuna bir boşluk bile gelmeyeceğini belirtmenize izin veren yeni yazdırma işlevini kullanabilirsiniz (ya da hangi tarafı seçerseniz seçin istemek):

from __future__ import print_function
...
print(item, end="")

Son olarak, dosya benzeri bir nesne döndüren sys modülünden içe aktararak doğrudan standart çıktıya yazabilirsiniz:

from sys import stdout
...
stdout.write( str(item) )

13

değişiklik

print item

için

print "\033[K", item, "\r",
sys.stdout.flush()
  • "\ 033 [K" satırın sonuna kadar temizlenir
  • \ r, satırın başına döner
  • flush deyimi, anında görünmesini sağlar, böylece gerçek zamanlı çıktı elde edersiniz.

Bu Python 2.7 için harika. \033[KKodu öğrendiğiniz yere bir referans verebilir misiniz ? Onlar hakkında daha fazla bilgi edinmek istiyorum.
Klik

printzaten dahili olarak yıkanır. Buna gerek yok. ekrana atmak zorunda olduğunuz yerden printfarklısys.stdout.write()
Gabriel Fair

5

Bence basit bir birleşimin çalışması gerekir:

nl = []
for x in range(1,10):nl.append(str(x))
print ' '.join(nl)

4
Bir anlama daha iyi okumak ve muhtemelen daha hızlı olacaktır: print ' '.join(str(x) for x in range(1, 10)).
Mu Mind

İkinci olarak bir liste kavrayışının kullanılması. Bu durumda bile okumayı kolaylaştırır.
Austin Henley

5

2.7'de kullandığım başka bir cevap sadece bir "." bir döngü her çalıştığında (kullanıcıya her şeyin hala çalıştığını belirtmek için) şudur:

print "\b.",

"." aralarında boşluk olmayan karakterler. Biraz daha iyi görünüyor ve oldukça iyi çalışıyor. \ B merak edenler için bir geri karakteri.


4

Çok karmaşık cevaplar. Python 3'ünüz varsa \r, baskının başına koyun ve ekleyin end='', flush=True:

import time

for i in range(10):
    print(f'\r{i} foo bar', end='', flush=True)
    time.sleep(0.5)

Bu yazacak 0 foo barsonra, 1 foo baryerinde, vb.


Teşekkür ederim, tam da ihtiyacım olan şey buyduprint('\r' + filename + " ", end = '', flush=True)
McPeppr

3

Sayıların birbirinin üzerine yazmasını sağlamak için şöyle bir şey yapabilirsiniz:

for i in range(1,100):
    print "\r",i,

Bu sayı, ilk sütuna yazdırıldığı sürece çalışmalıdır.

EDIT: İlk sütunda yazdırılmasa bile çalışacak bir sürüm.

prev_digits = -1
for i in range(0,1000):
    print("%s%d" % ("\b"*(prev_digits + 1), i)),
    prev_digits = len(str(i))

Bu kod test edildi ve Windows, Python 2.5 WIndows konsolunda iyi çalışıyor dikkat etmeliyim. Bazılarına göre, sonuçları görmek için stdoutun yıkanması gerekebilir. YMMV.


3

"Bu arada ...... Nasıl her yerde yenilemek böylece tek bir yerde mi yazdırmak sadece numarasını değiştirmek."

Gerçekten zor bir konu. Ne zack (konsol denetim kodu çıkışı) önerdi ulaşmak için tek yoldur.

(N) küfürleri kullanabilirsiniz, ancak bu temelde * nixes üzerinde çalışır.

Windows'da (ve burada ilginç kısım gider) (nadiren bahsedilir) (nedenini anlayamıyorum), WinAPI için Python bağlarını kullanabilirsiniz ( varsayılan olarak ActivePython ile http://sourceforge.net/projects/pywin32/ ) - değil bu zor ve iyi çalışıyor. İşte küçük bir örnek:

import win32console, time

output_handle = win32console.GetStdHandle(  win32console.STD_OUTPUT_HANDLE )
info = output_handle.GetConsoleScreenBufferInfo()
pos = info["CursorPosition"]

for i in "\\|/-\\|/-":
    output_handle.WriteConsoleOutputCharacter( i, pos )
    time.sleep( 1 )

Veya, kullanmak istiyorsanız print(ifade veya işlev, fark yok):

import win32console, time

output_handle = win32console.GetStdHandle(  win32console.STD_OUTPUT_HANDLE )
info = output_handle.GetConsoleScreenBufferInfo()
pos = info["CursorPosition"]

for i in "\\|/-\\|/-":
    print i
    output_handle.SetConsoleCursorPosition( pos )
    time.sleep( 1 )

win32console modülü Windows konsolu ile çok daha ilginç şeyler yapmanıza olanak tanır ... WinAPI'nin büyük bir hayranı değilim, ancak son zamanlarda ona karşı antipatinin en az yarısının WinAPI kodunu C'ye yazarak kaynaklandığını fark ettim. kullanımı çok daha kolay.

Diğer tüm cevaplar elbette harika ve pitonik, ama ... Ya önceki satıra yazdırmak istersem ? Ya da silmek ve aynı satırları tekrar yazmaktan çok satırlı metin mi yazıyorsunuz? Benim çözümüm bunu mümkün kılıyor.


2

Python 2.7 için

for x in range(0, 3):
    print x,

Python 3 için

for x in range(0, 3):
    print(x, end=" ")

1
In [9]: print?
Type:           builtin_function_or_method
Base Class:     <type 'builtin_function_or_method'>
String Form:    <built-in function print>
Namespace:      Python builtin
Docstring:
    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.

0

Sadece sayıları yazdırmak istiyorsanız, döngüden kaçınabilirsiniz.

# python 3
import time

startnumber = 1
endnumber = 100

# solution A without a for loop
start_time = time.clock()
m = map(str, range(startnumber, endnumber + 1))
print(' '.join(m))
end_time = time.clock()
timetaken = (end_time - start_time) * 1000
print('took {0}ms\n'.format(timetaken))

# solution B: with a for loop
start_time = time.clock()
for i in range(startnumber, endnumber + 1):
    print(i, end=' ')
end_time = time.clock()
timetaken = (end_time - start_time) * 1000
print('\ntook {0}ms\n'.format(timetaken))

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99100 aldı 21.1986929975ms

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99100 491.466823551ms aldı


Bunun yerine liste kavrayışı ile daha da hızlı olmalı map.
cji

Evet iyi örnekler. Hoşuma gitti, ancak ayrıştırma sonucunu göstermem gerekiyor. Önce ne kadar kalır yazdırmak daha i veritabanı öğeleri saymak.
Pol

0

Bunu yapmanın en iyi yolu \rkarakteri kullanmaktır.

Sadece aşağıdaki kodu deneyin:

import time
for n in range(500):
  print(n, end='\r')
  time.sleep(0.01)
print()  # start new line so most recently printed number stays

0

Python 3'te bunu şu şekilde yapabilirsiniz:

for item in range(1,10):
    print(item, end =" ")

Çıktılar:

1 2 3 4 5 6 7 8 9 

Tuple: Aynı şeyi bir tuple ile yapabilirsiniz:

tup = (1,2,3,4,5)

for n in tup:
    print(n, end = " - ")

Çıktılar:

1 - 2 - 3 - 4 - 5 - 

Başka bir örnek:

list_of_tuples = [(1,2),('A','B'), (3,4), ('Cat', 'Dog')]
for item in list_of_tuples:
    print(item)

Çıktılar:

(1, 2)
('A', 'B')
(3, 4)
('Cat', 'Dog')

Hatta demetinizi şu şekilde açabilirsiniz:

list_of_tuples = [(1,2),('A','B'), (3,4), ('Cat', 'Dog')]

# Tuple unpacking so that you can deal with elements inside of the tuple individually
for (item1, item2) in list_of_tuples:
    print(item1, item2)   

Çıktılar:

1 2
A B
3 4
Cat Dog

başka bir varyasyon:

list_of_tuples = [(1,2),('A','B'), (3,4), ('Cat', 'Dog')]
for (item1, item2) in list_of_tuples:
    print(item1)
    print(item2)
    print('\n')

Çıktılar:

1
2


A
B


3
4


Cat
Dog

Burada tüm örnekleri denedim ve hiçbiri python 3.8 çalışır. Lütfen daha fazla yanıt alın.
KOTZ

Python 3.7 ile test ettim
Stryker

Demek istediğim, bu seçeneklerin hiçbiri sorunun sonunda önerildiği gibi son sayının üzerine yazılmıyor.
KOTZ

0

Print ifadesinin sonundaki virgül yeni satırı atlar.

for i in xrange(1,100):
  print i,

ancak bunun üzerine yazılmaz.


0

Benim gibi mücadele edenler için, hem python 3.7.4 hem de 3.5.2'de çalışıyor gibi görünen aşağıdakileri buldum.

Aralığı 100'den 1.000.000'a çıkardım çünkü çok hızlı çalışıyor ve çıktıyı göremeyebilirsiniz. Bunun nedeni, ayarın bir yan etkisinin end='\r'son döngü yinelemesinin tüm çıktıyı temizlemesidir. Çalıştığını göstermek için daha uzun bir sayı gerekiyordu. Bu sonuç her durumda arzu edilmeyebilir, ancak benimki için iyiydi ve OP bir şekilde belirtmedi. Potansiyel olarak, yinelenen dizinin uzunluğunu vb. Değerlendiren bir if ifadesiyle atlatabilirsiniz. Benim durumumda çalışmanın anahtarı parantezleri "{}"birleştirmekti .format(). Aksi takdirde işe yaramadı.

Aşağıda olduğu gibi çalışması gerekir:

#!/usr/bin/env python3

for item in range(1,1000000):
    print("{}".format(item), end='\r', flush=True)

0
for item in range(1,100):
    if item==99:
        print(item,end='')
    else:
        print (item,end=',')

Çıktı: 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, 25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49, 50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74, 75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99


0

Veya daha da basit:

import time
a = 0
while True:
    print (a, end="\r")
    a += 1
    time.sleep(0.1)

end="\r" ilk baskının başlangıcından [0:] üzerine yazılır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.