1

I want to make a script which will type string letters one by one

def autotype(info):
    count = len(info) #Countign number of letters of the string
    splitlist = list(info) 
    i = int(count) #getting an error on this line! it accept i=int(0) but my loop doesnt work because of this
    while i>0:
        sys.stdout.write(splitlist[i])
        time.sleep(0.2)
        i -= 1

info = str("hello world")
autotype(info)

the error is: list index out of range how do i fix it?

4
  • OP: are you trying to go backwards through the string? Because that's what your code does. Commented Jul 22, 2013 at 17:36
  • @2rs2ts no, I just want to make a script which will type text exactly as it is Commented Jul 22, 2013 at 17:38
  • Then definitely do go with what I wrote originally. Commented Jul 22, 2013 at 17:40
  • 2
    don't forget to flush! (see my answer below) Commented Jul 22, 2013 at 17:41

7 Answers 7

7

The length of a list is the number of elements in a list. But, lists start at index 0, and so they will end at index length - 1. So, to fix your code as is, it should be i = count - 1. (You don't need to cast it to an int, it's already one.)

Better yet, rather than iterating using a counter in a while loop, just use a for loop. You can use the for loop to iterate over the characters in a string.

for ch in info:
    sys.stdout.write(ch)
    sys.stdout.flush()   # as mawimawi suggests, if you don't do this, it will
                         # actually just come out all on one line at once.
    time.sleep(0.2)

You also don't need to cast "hello world" to a string - it's already one.

Sign up to request clarification or add additional context in comments.

2 Comments

But note that this won't run through the string backwards.
Yeah, but does OP really want that? (I asked him as much in a comment.)
2

Your script is quite un-pythonic. Here is something that would do the same. Strings are iterables, so:

def autotype(info):
    for x in info:
        sys.stdout.write(x)
        sys.stdout.flush()  # you need this, because otherwise its' buffered!
        time.sleep(0.2)

That's all you need.

1 Comment

Good call on the flush(), I'll add it to mine (but credit you!)
2

You're starting your loop at i=len(info), which is one more than the final index in the string. The last index in a string (or other iterable) is len(string) - 1, because indices begin at 0.

Note that in Python, you can (and are encouraged to) make use of the natural language constructs and the fact that collections are easy to iterate over:

for letter in reversed(info): # Much clearer way to go backwards through a string
    sys.stdout.write(letter)

Since you've clarified in your comments that you actually want to go forwards through the text, you can just take out the reversed bit. The code as you posted will iterate backwards through the text, not forwards -- another benefit to using the standard iteration techniques is that it's much easier to see if you've done something you didn't mean to do!

for letter in info: # Very clear that you're going forward through the string
    sys.stdout.write(letter)

Finally, as others have mentioned, you should add an explicit call to sys.stdout.flush() after every write, because otherwise there's no guarantee that you'll see output at regular intervals (it could be written to the buffer but not flushed to the screen until much later).

8 Comments

I agree, this is pythonic way and should be used. Also no explicit type declarations are needed. I would also change sys.stdout.write to print.
@Dārayavahuštdi Is there a way to do print and flush the buffer every time to make it look like it's getting typed?
@Dārayavahuštdi print will flush the buffer (I think), but it also adds spaces before each letter (without further manipulations), which is presumably not what the OP wants.
@2rs2ts print does flush the buffer as far as I know, but it introduces formatting problems. These can be circumvented with print(letter, sep=''), but I think the explicit flush is probably better anyway.
@HenryKeiter When I tried for c in "hello": time.sleep(0.2); print c, I got it all at once after 1 second. An explicit sys.stdout.flush() a la mawimawi's answer worked as expected.
|
0

Lists are zero-indexed, so the last element is at len(info)-1.

To fix this, you need to subtract 1 from the count:

i = int(count) - 1

Comments

0

Indexes are counted from zero... if you have 5 items in a list, then indexes are 0,1,2,3,4

you are setting index out of bounds in this line:

i = int(count)

If count is 5 then max index is 4. To fix this change that line into:

i = int(count) - 1

Next thing, you won't print the first character. to fix that change a line:

while i>0:

into:

while i>=0:

By the way all your characters are printed backwards.

Comments

0

Unidiomatically, but concisely:

import time
import sys

autotype = lambda instr:map((lambda ch:(sys.stdout.write(ch), time.sleep(0.2))), instr)

autotype("hello world")

The main problem with the above code is that it's not usual to sequence two functions using tuple if you don't care for their return values.

Comments

0

Here is code to "make a script which will type string letters one by one"

print info

If what you need is to type letters in a string consecutively, there is no need to reinvent the wheel.

More than likely, your question was underspecified.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.