Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError: can't pickle odict_items objects in python 3.5 #560

Closed
dangusev opened this issue Nov 14, 2016 · 7 comments
Closed

TypeError: can't pickle odict_items objects in python 3.5 #560

dangusev opened this issue Nov 14, 2016 · 7 comments

Comments

@dangusev
Copy link

Hello, I caught an error during instantiation of FilterSet-derived class in python>=3.5. In 3.4 everything works ok.

File "/home/dan/venvs/notes3.5/lib/python3.5/site-packages/django_filters/filterset.py" in __init__
  291.         self.filters = copy.deepcopy(self.base_filters)

File "/home/dan/venvs/notes3.5/lib/python3.5/copy.py" in deepcopy
  182.                 y = _reconstruct(x, rv, 1, memo)

File "/home/dan/venvs/notes3.5/lib/python3.5/copy.py" in _reconstruct
  320.                 value = deepcopy(value, memo)

File "/home/dan/venvs/notes3.5/lib/python3.5/copy.py" in deepcopy
  182.                 y = _reconstruct(x, rv, 1, memo)

File "/home/dan/venvs/notes3.5/lib/python3.5/copy.py" in _reconstruct
  297.             state = deepcopy(state, memo)

File "/home/dan/venvs/notes3.5/lib/python3.5/copy.py" in deepcopy
  155.         y = copier(x, memo)

File "/home/dan/venvs/notes3.5/lib/python3.5/copy.py" in _deepcopy_dict
  243.         y[deepcopy(key, memo)] = deepcopy(value, memo)

File "/home/dan/venvs/notes3.5/lib/python3.5/copy.py" in deepcopy
  155.         y = copier(x, memo)

File "/home/dan/venvs/notes3.5/lib/python3.5/copy.py" in _deepcopy_dict
  243.         y[deepcopy(key, memo)] = deepcopy(value, memo)

File "/home/dan/venvs/notes3.5/lib/python3.5/copy.py" in deepcopy
  174.                         rv = reductor(4)

Exception Type: TypeError at /notes/
Exception Value: can't pickle odict_items objects

Example of my FilterSet class. Fields DateTimeFIlter and CommaSeparatedCharFilter are custom:

class NoteListFilterset(django_filters.FilterSet):
    strict = STRICTNESS.RAISE_VALIDATION_ERROR

    keywords = CommaSeparatedCharFilter(name='keyword', lookup_expr='in')
    datetime_from = DateTimeFilter(name='datetime', lookup_expr='gte')
    datetime_to = DateTimeFilter(name='datetime', lookup_expr='lte')
    get_hidden = django_filters.MethodFilter(method='filter_by_get_hidden')
@rpkilby
Copy link
Collaborator

rpkilby commented Nov 14, 2016

Hi @dangusev. Initial reaction is that it doesn't make sense. Two thoughts:

  • The test suite is ran against python 3.5, this kind of issue would have been picked up.
  • base_filters should be an OrderedDict, not an odict_items. Is something overriding base_filters?

@dangusev
Copy link
Author

Sorry, my bad). I have a lot of code like this:

category = ChoiceField(choices=CATEGORIES.items())

When copy.deepcopy() is being called on self.base_fields it tries to pickle choices of fields and fails, because choices have type dict_items.

@Ryanb58
Copy link

Ryanb58 commented Dec 12, 2017

For those still running into this issue, I solved it like so:

list(CATEGORIES.items())

@paulschreiber
Copy link

paulschreiber commented Oct 12, 2020

[With Python 3.85 and Django 3.1.1] Similarly, I’m getting this error in one of my list views:

TypeError: cannot pickle 'dict_items' object

Nothing in the backtrace is in my code:
https://pastebin.com/S4xn8zpT

Turns out the problem was adding a choices list to a CharField in my model:

fails:

record_request_status = models.CharField(max_length=4, null=True, choices=RECORD_REQUEST_STATUS)

works ok:

record_request_status = models.CharField(max_length=4, null=True)

RECORD_REQUEST_STATUS is a dict:

with open('case-manager/src/json_fixtures/record_request_status.json') as json_file:
		RECORD_REQUEST_STATUS = json.load(json_file).items()

Assigning that same choices list to other CharFields in the model works fine.
Assigning other choices lists to record_request_status also fails.

this works:

record_request_status = models.CharField(max_length=4, null=True, choices=list(RECORD_REQUEST_STATUS))

Can someone explain what's going on?

@Ryanb58
Copy link

Ryanb58 commented Oct 19, 2020

@paulschreiber in your situation RECORD_REQUEST_STATUS returns a dict_items type instead of just a primitive List or Tuple.. dict_items is not a known type for pickle to convert so it throws that error. dict_items does have the proper methods implemented to count as an iterator so the list method works in converting it and thus choices can finally accept what you are passing in.

Hopefully, that explains it in good form, it's been a few years since I last looked at this.

@paulschreiber
Copy link

@Ryanb58 I don't understand why it fails only for this field, but works for all other fields in my various models. In each case, I'm reading in a JSON file that's a dictionary.

@Ryanb58
Copy link

Ryanb58 commented Oct 19, 2020

@paulschreiber I'm interested in the problem but also don't want to blow up this thread. Sounds like it might be something outside the scope of this specific project. I'll shoot you an email.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants