37

It's kind of boring to always see the >>> prompt in Python. What would be the best way to go about randomly changing the prompt prefix?

I imagine an interaction like:

This is a tobbaconist!>> import sys
Sorry?>> import math
Sorry?>> print sys.ps1
Sorry?
What?>>
SuperBiasedMan
  • 9,814
  • 10
  • 45
  • 73
mircealungu
  • 6,831
  • 7
  • 34
  • 44
  • 12
    Just make sure you change it back before asking questions that include interpreter sessions... – jonrsharpe Nov 12 '15 at 10:29
  • 5
    @jonrsharpe *"Why isn't my interpreter a tobbaconist!?"* – SuperBiasedMan Nov 12 '15 at 10:33
  • On the contrary, I think about making the questions stand out even more by using colors in the prompt (e.g. sys.ps1 = '\033[01;31mwhat?>>>\033[00m ') – mircealungu Nov 12 '15 at 13:40
  • 1
    You could even have random colours to go with the tobacconist. – Holloway Nov 12 '15 at 16:23
  • 1
    If you're changing the prompt colour and using readline, take a look at [this](https://stackoverflow.com/questions/9468435/look-how-to-fix-column-calculation-in-python-readline-if-use-color-prompt) question. – Holloway Nov 12 '15 at 16:24
  • 2
    Paging @HovercraftFullOfEels – Mike G Nov 12 '15 at 17:03
  • 1
    Yes, this might make his nipples explode with delight. –  Nov 12 '15 at 17:10
  • 2
    It might be a good idea to keep all of your random prompts a fixed width. Unless you like the extra challenge of counting your spaces and ignoring when things don't look lined up to make sure you indent properly. – tpg2114 Nov 12 '15 at 18:52

4 Answers4

66

According to the docs, if you assign a non-string object to sys.ps1 then it will evaluate the str function of it each time:

If a non-string object is assigned to either variable, its str() is re-evaluated each time the interpreter prepares to read a new interactive command; this can be used to implement a dynamic prompt.

Well now it's obvious, you should make it dynamic! Make an object with a __str__ method where you can place any logic you want:

class Prompt:
    def __str__(self):
        # Logic to randomly determine string
        return string

You can also make changes or insert things into this class as you go too. So for example, you could have a list of messages in Prompt that you append to, or change, and that will affect the console message.

SuperBiasedMan
  • 9,814
  • 10
  • 45
  • 73
21

Try this:

>>> import sys
>>> import random
>>> class RandomPrompt(object):
...     prompts = 'hello >', 'hi >', 'hey >'
...     def __repr__ (self): return random.choice(self.prompts)
... 
>>> sys.ps1 = RandomPrompt()
hello >1
1
hi >2
2
Klaus D.
  • 13,874
  • 5
  • 41
  • 48
  • `__repr__()` or `__str__()`? – glglgl Nov 12 '15 at 12:20
  • 6
    @glglgl, the prompt is generated by calling `__str__()`. If it's not defined, it defaults to `__repr__()` so in this case it doesn't matter which. – Holloway Nov 12 '15 at 12:38
  • Just to be sure: why would you want to write a class in this example. Wouldn't `def RandomPrompt(): prompts = [...]; return choice(prompts)` suffice? – andrepd Nov 12 '15 at 22:47
  • A function would run the initialization every time. In this particular case it wouldn't be expensive but it's generally a good practice to divide the initialization from the actual code. – Klaus D. Nov 13 '15 at 01:34
19

For changing the prompt, we use

>>>import sys
>>>sys.ps1 = '=>'
=>

Now the way to do it randomly would be something like this:

import random
import sys

random_prompts = ['->', '-->', '=>', 'Hello->']
sys.ps1 = random.choice(random_prompts)

To execute this when your python interpreter starts, you can follow this guide: https://docs.python.org/2/tutorial/appendix.html#the-interactive-startup-file

Yash Mehrotra
  • 3,032
  • 1
  • 21
  • 24
8

Nice question. The >>> prompt is in sys.ps1, the ... in sys.ps2. The next question would be how to change this randomly. Just as a demonstration of changing it by hand:

>>> import sys
>>> sys.ps1 = '<<<'
<<<sys.ps1 = '<<< '
<<< sys.ps2 = '.?. '
<<< for i in line:
.?. 
serv-inc
  • 35,772
  • 9
  • 166
  • 188