2

I have seen some code (e.g. this tutorial from dropbox) that probably needs to work for quite a wile with Python 2.X but probably also with Python 3.X

How should those projects deal with raw_input?

I think something like

#!/usr/bin/env python


def input_string(question=""):
    """A function that works for both, Python 2.x and Python 3.x.
       It asks the user for input and returns it as a string.
    """
    import sys
    if sys.version_info[0] == 2:
        return raw_input(question)
    else:
        return input(question)

# Example
answer = input_string("What is your name? ")
print(answer)

might be a good way, but I am not too sure about it.

Are there "official" advice (e.g. in form of PEPs) how to deal with it? How is this done by now?

Martin Thoma
  • 124,992
  • 159
  • 614
  • 958
  • have you looked at https://docs.python.org/2/library/2to3.html#using-2to3 – Padraic Cunningham Aug 19 '14 at 18:18
  • 1
    Try this? http://stackoverflow.com/a/7321970/350351 – Daenyth Aug 19 '14 at 18:18
  • Also, note the recommendation here: http://stackoverflow.com/a/5868543/716118. One alternative is simply to write your app in Python 2.x and then use `2to3` to convert it. – voithos Aug 19 '14 at 18:19
  • 2to3 does change source from 2.x Python code to 3.x Python code. Please correct me if I'm wrong, but the generated code will not work any more for Python 2.x. That is not what I want. I want code that works for both, Python 2 and Python 3. – Martin Thoma Aug 19 '14 at 18:27
  • 1
    Do you want the same script to work both in 2.x and 3.x? – J0HN Aug 19 '14 at 18:27
  • @J0HN: Yes. (And I would like to know how big libraries like numpy / scipy / beautiful soup deal/dealt with the transition from 2.x to 3.x) – Martin Thoma Aug 19 '14 at 18:29
  • I believe numpy/scipy/etc. just provide (at least) two "instances": one for 2.x and one for 3.x. Also I believe, the transition was mostly manual - python 3 was released December 2008 and not everyone have already support it. But I'm not affiliated with them, so it's just my speculations – J0HN Aug 19 '14 at 18:30
  • I don't have python 2 at hand, so won't post this as an answer as I haven't tested it. If you can use external packages, [six](https://pypi.python.org/pypi/six) is a way to go, as it contains `input` and is specifically designed to provide bridge implementations working both in 2.x and 3.x. If you can't your way is perfectly valid. Only improvement to make is to remember if `raw_input` is available, something like `compatible_input = raw_input if sys.version_info[0] == 2 else input` – J0HN Aug 19 '14 at 18:39

2 Answers2

0

How about this?

try: 
    input = raw_input
except NameError: 
    pass
print("Hi " + input("Say something: "))
Chrispresso
  • 3,660
  • 2
  • 19
  • 31
  • There's `input` in python 2.x and you just overwritten it. – J0HN Aug 19 '14 at 18:32
  • 1
    I typically do exactly this but name it something else, like `input_func`. Then, rather than `pass` under the `except` block, I assign `input` instead. This has the advantage over the below answer of needing only one try/except at the top of the file, rather than one each time you need user input. – Two-Bit Alchemist Aug 19 '14 at 18:35
  • 1
    @J0HN So? This is *exactly* what the OP wants. Python 2.x `input` is **evil**. You ***never*** want to use it. 99% of the time you want to use things like `int(raw_input())` or `float(raw_input())` the other 0.99% of the time you want to use `ast.literal_eval(raw_input())` and only in the 0.001% of the usages you really want `eval(raw_input())` [which is what `input` does]. – Bakuriu Aug 19 '14 at 18:39
  • 1
    @Bakuriu, thanks for really emotional comment. Yes, I'm aware of this behavior, and no, I don't think it excuses overwriting a builtin. And no, this is one possible solution to the problem OP have, but not *exactly* what was asked for. – J0HN Aug 19 '14 at 18:42
  • 1
    @J0HN except that the OP is **not** overwriting the built-in. To overwrite the built-in you'd do: `try: __builtins__.input = raw_input; except NameError: pass`. The solution in this answers creates a *global variable* called `input`. It does *not* mess with other modules and as such is perfectly safe to use. In fact it enforces a good practice. – Bakuriu Aug 19 '14 at 18:45
-1

You have a couple of options

Option 1 - Just use 2to3

2to3 is a python program that will convert your program appropriately, resolving this issue

From the above link:

Here is a sample Python 2.x source file, example.py:

def greet(name):
    print "Hello, {0}!".format(name)
print "What's your name?"
name = raw_input()
greet(name)

It can be converted to Python 3.x code via 2to3 on the command line:

$ 2to3 example.py 

A diff against the original source file is printed. 2to3 can also write the needed modifications right back to the source file. (A backup of the original file is made unless -n is also given.) Writing the changes back is enabled with the -w flag:

$ 2to3 -w example.py 

After transformation, example.py looks like this:

def greet(name):
    print("Hello, {0}!".format(name)) 
print("What's your name?") 
name = input() 
greet(name)

Option 2 - use a try/except block

try:
    return raw_input(question)
except NameError:
    return input(question)

This will help you avoid having to re-run 2to3 every time you change something. To avoid doing this ad nauseum you can put it inside of a function like so

def real_input(astring=""):
    try:
        return raw_input(astring)
    except NameError:
        return input(astring)

and then just use real_input() whenever you need user input

Dan Oberlam
  • 2,435
  • 9
  • 36
  • 54
  • Three big problems with this answer. (1.) You can do this very easily without using a converter tool, using the same script compatible with both versions of Python. (2.) Your "Option 2" requires a try/except everywhere rather than one at the top. (3.) You didn't even bother to figure out `WhateverErrorThisIs` which would take 2 seconds in a Python interpreter. – Two-Bit Alchemist Aug 19 '14 at 18:38
  • @Two-BitAlchemist Regarding (1.) that's why I provided the other option (and the OP was unclear about what, if anything else, might be necessary to be changed to be compatible). (2.) I intended for option 2 to be placed in a function (such as the OP provides) that would then be called instead of `raw_input()` or `input()` (3.) Fair point. I don't have Python 3 on my machine and I didn't have the time to look it up – Dan Oberlam Aug 19 '14 at 21:24