0

In Python 2, I could do something like this,

test = "6L"
print(long(test))
>>> 6

In PEP 237, int and long were unified.

Now, my problem is, if I had a database which contained Python 2 long representation as strings, how can I convert it back to int in Python 3.

In Python 3,

test = "6L"
print(int(test)) #since no long type
>>> ValueError: invalid literal for int() with base 10: '6L'

So, is their a built-in way to handle this problem ? I mean I know I could go and remove the trailing 'L' in the string version of 6L, but this seems like a nasty thing to do for this simple task.

EDIT

Just to clarify on @BurhanKhalid comment. As in the example, those are stored as string literal. In Python 2, it was possible to cast them directly and this is the behavior I'm looking for in Python 3 (if possible).

scharette
  • 9,437
  • 8
  • 33
  • 67
  • 4
    "but this seems like a nasty thing to do for this simple task." Seems like a simple solution for a simple task. – FHTMitchell Jun 22 '18 at 13:02
  • Why does `int(test[:-1])` seem nasty? – Nick is tired Jun 22 '18 at 13:03
  • 7
    I'm not sure I understand, _" if I had a database which contained Python 2 long representation"_ a database would store its own representation, of the type of the column; you would not expect to see `6L` in the database (unless you stored it as a literal string). The DB API will take care of the translation of the database value to Python types. Can you produce a test case from a DB? – Burhan Khalid Jun 22 '18 at 13:04
  • 4
    @NickA that would be problematic if you had mixed `int` and `long`, `.rstrip('L')` might be safer. – jonrsharpe Jun 22 '18 at 13:04
  • 3
    @NickA That's actually a bad solution in case not all db entries follow this convention. `int(test.strip('L'))` is much better – DeepSpace Jun 22 '18 at 13:05
  • 1
    @jon and deep right enough, that would be much better, although the question stands, what would be wrong with `int(test.rstrip('L'))`? – Nick is tired Jun 22 '18 at 13:05
  • @BurhanKhalid not sure if it is enough, but see [this](https://stackoverflow.com/q/11764713/7692463), I think it is a similar case. – scharette Jun 22 '18 at 13:08
  • @FHTMitchell I felt like manipulating a string version of an handled type was kind of messy. I mean were talking about two iteration of the same language, They wanted to unified the two types. I really thought that `int(test)` would be supported. I guess I'm wrong... – scharette Jun 22 '18 at 13:11
  • @BurhanKhalid also, _unless you stored it as a literal string_, isn't exactly my use case in the question ? – scharette Jun 22 '18 at 13:13
  • Well, I think the answer to your question is a simple "no". There's no built-in way to handle that. – glibdud Jun 22 '18 at 13:21
  • @glibdud If this is really the case, which I would be surprised, then thank you for actually answering the question I was asking for. – scharette Jun 22 '18 at 13:23

1 Answers1

1

If you have stored string literals in the database, then short of accessing the database with Python 2, converting to longs and storing them properly, there is no other way save for string parsing.

You can use regular expressions, or simply drop the last character if its L.

try:
   value = int(possible_long)
except ValueError:
   if possible_long[-1] == 'L':
       value = int(possible_long[:-1]) # this can still raise an exception,
                                       # but we need to raise at this point
                                       # as the value isn't a string repr of float

Normally, you don't need to worry about type conversion. The Python database drivers will make sure that the data returned is of the correct type for the version of Python being used.

You must, however, give the correct representation in the query string to convert values. If you use string concatenation, you will not benefit from this behavior.

When you print the result of a database call, you are seeing the translated values and are seeing Python types, not the literal value from the database.

They do not simply "copy and paste" the values from the database. In your comment you referred to this question, specifically this piece of code:

{'estimated': '', 
 'suffix': '', 
 'typeofread': 'g', 
  'acct_no': 901001000L, 
  'counter': 0, 
  'time_billed': datetime.datetime(2012, 5, 1, 9, 5, 33), 
  'date_read': datetime.datetime(2012, 3, 13, 23, 19, 45), 
  'reading': 3018L, 
  'meter_num': '26174200'}

This is a result of the type conversion that the database drivers do for you. What you are seeing here is the Python data type equivalent, for the values received from the database.

The value 901001000L is the Python long type, for the data received from the database. You can tell its not a string literal because it is not quoted, unlike '26174200' which is quoted and thus is a string literal; most likely the database column type for meter_num is a character or string type.

This example is from Python 2, thus the L, if you ran the same code against Python 3, you would not see the L in the result.

To confirm this behavior, access the database with any other client (such as the mysql> client) and you will see that the value is not stored as nine zero one zero zero one zero zero zero L but rather the native type that the database column represents.

Burhan Khalid
  • 169,990
  • 18
  • 245
  • 284