2016-07-01 4 views
0

Für mein Open-Source-Projekt (bquery) stoße ich auf ein Problem mit Cython-Codes, das in Python 2.7 einwandfrei funktioniert, aber in Python 3.x gibt es einen Fehler. Für den gesamten Code, siehe: https://github.com/visualfabriq/bquery/pull/66Cython Bytes Fehler in Python3

Aber um eine Idee zu geben: Die Idee des Codes besteht darin, eine Zählung distinct/unique von Werten für jedes Element in einer Gruppierung. Ich mache eine Hash-Prüfung von zwei Werten, um sicherzustellen, dass sie eindeutig sind (andernfalls würde ich eine Hash-Tabelle pro Gruppe benötigen, die in vielen Fällen effizienter ist, aber nicht hier wie bei der zugrundeliegenden Technologie, die ich nicht durch die Werte laufen lassen möchte mehrmals). Um die Werte eindeutig zu machen, erstelle ich eine verkettete Zeichenfolge (mit einem Trennzeichen dazwischen) und überprüfen Sie dann die Hash-Tabelle. So weit, ist es gut! Verleiht in Python2 ein perfektes Ergebnis und ist relativ schnell. Aber in Python 3 laufe ich auf Fehler.

Dies ist der Code:

cdef 

    kh_str_t * table 
    char * element_1 
    char * element_2 
    char * element_3 
    int ret, size_1, size_2, size_3 

v = in_buffer[i] 
# index 
size_1 = len(bytes(current_index)) + 1 
element_1 = < char * > malloc(size_1) 
strcpy(element_1, bytes(current_index)) 
# value 
size_2 = len(str(v)) + 1 
element_2 = < char * > malloc(size_2) 
strcpy(element_2, bytes(v)) 
# combination 
size_3 = size_1 + size_2 + 2 
element_3 = < char * > malloc(size_3) 
strcpy(element_3, element_1 + '|' + element_2) 
# hash check 
k = kh_get_str(table, element_3) 
if k == table.n_buckets: 
    # first save the new element 
    k = kh_put_str(table, element_3, & ret) 
    # then up the amount of values found 
    out_buffer[current_index] += 1 

Und das ist der Fehler:

====================================================================== 
ERROR: test_groupby_08: Groupby's type 'count_distinct' 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "/home/carst/venv3/lib/python3.5/site-packages/nose/case.py", line 198, in runTest 
    self.test(*self.arg) 
    File "/home/carst/PycharmProjects/bquery/bquery/tests/test_ctable.py", line 516, in test_groupby_08 
    result_bcolz = fact_bcolz.groupby(groupby_cols, agg_list) 
    File "/home/carst/PycharmProjects/bquery/bquery/ctable.py", line 226, in groupby 
    bool_arr=bool_arr) 
    File "/home/carst/PycharmProjects/bquery/bquery/ctable.py", line 161, in aggregate_groups 
    raise e 
    File "/home/carst/PycharmProjects/bquery/bquery/ctable.py", line 155, in aggregate_groups 
    agg_op) 
    File "bquery/ctable_ext.pyx", line 452, in bquery.ctable_ext.__pyx_fuse_2_0aggregate (bquery/ctable_ext.c:27585) 
    cpdef aggregate(carray ca_input, carray ca_factor, 
    File "bquery/ctable_ext.pyx", line 653, in bquery.ctable_ext.aggregate (bquery/ctable_ext.c:27107) 
    strcpy(element_2, bytes(v)) 
TypeError: 'float' object is not iterable 

ich etwas sehr offensichtlich mit Blick auf sein muss, aber ich weiß nicht, was ich fehle. Jede Anleitung oder Hilfe würde sehr geschätzt werden !!!

BR

Carst

Antwort

1

In Python2.x bytes ist ein Alias ​​für str daher

>>> bytes(42.0) 
'42.0' 

In Python3.X hat jedoch bytes einen neuen Konstruktor, der, da alles andere als int oder str behandelt es als iterable von Ints. Also der Fehler, den du siehst.

>>> help(bytes) 
class bytes(object) 
| bytes(iterable_of_ints) -> bytes 
| bytes(string, encoding[, errors]) -> bytes 
| bytes(bytes_or_buffer) -> immutable copy of bytes_or_buffer 
| bytes(int) -> bytes object of size given by the parameter initialized with null bytes 

dieses Problem umgehen, verwenden:

str(v).encode() 

Ja, es ist nicht schön und erfordert zwei Kopien von Daten, aber es funktioniert sowohl Python 2 und 3

+0

Ich konnte küssen Sie! Das Einzige, was noch läuft, ist das "element_1 + '|' + element_2 "Teil, wo ich bekomme" kann nicht concat Bytes to str "Fehler. aber mach es b '|' funktioniert auch nicht. versuchen einige Alternativen atm. – Carst

+0

und behoben (indem Sie das Trennzeichen in einen temporären '|' .encode() Wert setzen. Vielen Dank Sergei! – Carst

+0

Froh, dass es geklappt hat! Ich habe vor kurzem mit einem ähnlichen Fehler ziemlich viel gekämpft :) –