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
Convert to Python 3 #1407
Convert to Python 3 #1407
Conversation
…d some manual fixes)
Thanks for all this work, @cbrnr, this is awesome!
There's many great Python-3-only features that cannot be used when supporting both Python 2 and 3, like keyword-only arguments or extended iterable unpacking. IPython, for example, has also made the switch to Python-3-only for that reason. Still, there will be a painful transition period, and I'm afraid it will last until Python 2 is EOL (2020). Looking very much forward to finally dumping my Python 2 installation, which I only have to keep around for PsychoPy these days! Tests on Travis don't pass (actually don't really start running), could you look into this please? |
Sure, I'd dump Python 2 support immediately if the Python 3 version worked. Just like you I only have a Python 2 env just for PsychoPy... Regarding the Travis issue: I didn't expect that it passed because this is a very first premature step 😄. Turns out that it fails because it uses a Python 2.7 env, so we need to set up a Python 3 (preferably 3.6) environment. |
I just realized you also got rid of all the |
Yes, apparently that's what the 2to3 tool does. However, like I said, it will be difficult to maintain compatibility to both versions mainly because of the string changes. I'm not super familiar with converting this stuff so that it runs on both versions, but the six package might be useful. However, this introduces yet another layer of complexity, and prevents us from using all the nice Python 3 features. Why don't we create a Python 3 only branch and try to get that to work? |
Because this would essentially fork development. We'd have to freeze the Python 2 branch, otherwise we'd have to implement all new features in both branches. Yet we'd STILL have to provide bug fixes for the Python2 branch. I'm worried this might not be the best approach, given the extremely scarce development resources of this project. |
psychopy/app/builder/builder.py
Outdated
@@ -2111,7 +2111,7 @@ def renameRoutine(self, name, event=None, returnName=True): | |||
# namespace: | |||
name = exp.namespace.makeValid( | |||
name, prefix='routine') | |||
if oldName in self.exp.routines.keys(): | |||
if oldName in list(self.exp.routines.keys()): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand these changes, could someone explain? Why the explicit conversion?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In Python 2, d.keys()
returns a list. Python 3 returns a dict_keys
view. Therefore, if the old behavior was really intended, it is correct to explicitly convert the return value into a list. However, in this particular case I would simply write if oldName in self.exp.routines
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very good point, thank you. I agree with you on the proposed simplification.
That said, the approach I proposed is also not very efficient. Like you already pointed out, even creating a 2/3-compatible code base is going to be difficult. It's going to introduce another layer of complexity -- the IPython project didn't remove it for nothing! What I could realistically imagine is something like this:
|
Yep, that's what I meant 😄 - sounds like a good approach! |
Hello, It would be helpful to plan and outline the 2 to 3 transition, it needs to be done someday, and attempts have been intermittent (rightfully so given the complexity). I'm working on stereoscopic 3D libraries, they are quite substantial (new window classes, 3D object stimuli, etc.) and will likely have an unstable API for some time afterwards. If there is going to be a Python 2.x code freeze, I would like to postpone a release until there is a functioning Python 3 fork. It would be a better use of the resources I have to support only one version of PsychoPy. |
It seems like this topic needs more discussion. I think we all agree that we should switch to Python 3 sooner than later, but we all have limited resources. However, we are already seeing popular packages getting developed for Python 3 only. The IPython project is a good example which PsychoPy could follow. That is, create one last Python 2 release which will be supported for some time in the future, but focus all efforts on a Python 3 only version for all future releases. In other words, I'd stop adding new features to the current version until everything works with Python 3. I also agree with @mdcutone that supporting only one Python version is a better use of our resources. |
Note that monitors saved with Python 2 need to be recreated with Python 3 because they are stored in pickle objects (stored this information as JSON or something similar would be a better option IMO). |
Status update: http://www.psychopy.org/coder/tutorial1.html is working. |
Yeah I also brought this up recently for saving of experiments. A change like this would be very welcome. |
Generally I think we should not compile such super-mega-ultra-huge commits, but "slowly" move from module to module. I guess nobody is able to review such a massive PR at once and understand its implications. Splitting this up into many small commits, one per module or so, would make things much easier. |
For monitor calib files I agree with it - they are simple dict-type objects that would be easily represented in a json format (barely existed in 2003, when calibration code was first written). For ExperimentHandler it would be a big job to work out how to save such large, arbitrary objects in JSON |
Clemens, thanks for testing this and seeing where the issues will crop up.
I'm guessing this is currently "kicking the tyres" for now rather than the final conversion. Until we can get wx4 working this is a non-starter for me thanks again, Jon |
@lindeloev had recently brought up the idea of splitting the GUI app development from the library (unfortunately I cannot seem to find his comment and @peircej's response anymore). Maybe it's time to reconsider this possibility? |
Splitting the app from the lib is going to be tricky, and I don't think it's worth the effort. But it also doesn't alter the current situation. I would still need both the lib and the app to be compatible before either of them switch, whether or not they are in a single repos. |
I agree with @peircej, splitting the project will be very difficult to manage. In the case of Psychopy, GUI and libs will be using two different python versions which complicates things for deployment and development. Creating an outline of required tasks and have developers assign themselves should better coordinate this transition process. |
The staircase example from the coder tutorial works. Note that |
Let's not implement any major changes before the Python 3 conversion (although I think splitting psychopy into a lib and a GUI part is a good idea). So far, I managed to get some examples from the tutorial to work. Even wxPython Phoenix works (but the |
…re still many issues - but it's a start!
The GUI parts now start with Python 3 (builder and coder). |
I've added your commits to branch python3 in upstream. They can't be pulled into master anytime soon. |
Thanks @peircej I'll make sure to track this branch. |
Where do we discuss issues related to Python 3 now that you've closed this PR? I was planning on pushing more changes... |
I closed it because there's no short-term intention of merging with the master branch. Can you submit a pull request to the python3 branch instead? We can refer back to this one from there. I could reopen this if you like tho |
Maybe it is easiest if we just keep this PR open and use my |
ah, actually it looks like I can't do that. The 'reopen' button or is commented out and complains that the "branch was force-pushed recreated". Back to my prev plan then; submit a pull request from your branch to the psychopy/python3 branch and we can reconvene there |
Sorry if I've not followed the discussion close enough - but is there no possibility to make psychopy py2&3 compatible? Many projects have |
I'm in the same boat as @mmagnuski . |
My feeling is that we should only decide to drop the py2 support in places where it's actually needed. Many of the changes that @cbrnr has made will "just work" in both places e.g.:
Some of the changes the 2to3 has made are quite annoying and break things unnecessarily e.g.:
A few further changes would really not be a big deal to have a line that says: if PY2:
doThis()
else:
doThat() BUT we might some pieces of code where writing the dual-compatible version will be hard. I don't know. i.e. I'm not ready to commit either way. If there is a place that requires break compatibility then we'll do it. I do think we should proceed with changes that support both options where possible and keep an eye out for places where that's a problem. |
I don't think there's a need to put that extra burden on us to make the code compatible with both 2 and 3. Of course, if there is an easy way that works in both versions without too much additional work we should go for it, but that's not going to be the case all the time. I'd rather not start with branches of code conditioned on the version of Python, this soon gets pretty ugly (instead, the Consider the users of PsychoPy. Most people will likely want to use the GUI and just install the prebuilt installer packages, which come with their own Python version. These people probably won't care if this Python version is 2 or 3. Others who want to use PsychoPy in their scripts (like most of the people here in this discussion) will use Python 3, so they too shouldn't care about Python 2 compatibility. Do you think there is one single good reason why anyone would still need Python 2 support for PsychoPy? I doubt that a machine that only supports Python 2 (such as some arcane commercial Linux versions like Red Hat) is really suitable for presenting stimuli with PsychoPy in the first place... So unless there are dependencies that don't work with Python 3 there is no reason to keep supporting Python 2. Of course anyone is welcome to put in the extra effort of looking through all changes that Finally, this website lists projects that will remove Python 2 support by 2020. I really like the idea of releasing one last LTS version for Python 2 and stick with Python 3 for all newer version. |
This is asserted but not yet clear to me. When I wrote pyosf I wrote it to be cross-compatible. In 2400 lines of code I needed just 2
I agree. The aim of cross-compatible code is the only way I see to avoid this. If the codebase fully drops support for py2 then there must be a period both branches while we troubleshoot the py3 code.
I really really do. More than most.
A user that has no code components (e.g. no print statements) in their experiment will be unaffected. Any Builder user with a print statement will get an error and they'll be confused. Sure, they will have to deal with this eventually but we could make the transition easier for them.
You're talking about coding enthusiasts. There is another massive sector of users that prefer to write code but it's a struggle and they don't relish changing it (ever). They do care about python2 and they are the majority. Note that of the 16,000 monthly PsychoPy users only 70 people have ever made a contribution to the project. The people involved with psychopy on github are not the "average" user and we shouldn't forget what that "average" user is actually like. Again, we're agreed they'll have to switch one day but Im' hoping we don't need to choose for them when that day is. |
It's easier if you start from scratch. It's way more difficult if you have such a large project as PsychoPy.
I disagree. They should have to deal with it right now.
Yes, I agree that people contributing here are certainly not the average user. Many people will have existing experiments that they won't want to convert. However, there will always be that last Python 2 LTS version they can use.
I disagree. The average user is neither aware of the ongoing Python 2/3 transition, and nor should they have to care. The developers must make this decision, otherwise it will be difficult to maintain this code before long. Anyway, I'm happy to contribute more, but it would be good to have a final roadmap/decision on how you would like to go about it. Postponing the decision won't help at the end of the day. |
The decision is:
|
This is a superset of the changes in psychopy#1407 (thanks @cbrnr for revealing this cool stuff!) - py3 dict.keys() doesn't return a list so do one of: - list(myDict.keys()) - list(myDict) # easier but less explicit Also sorted() func has existed since python2.4 so instead of: keys = myDict.keys() keys.sort() we can do: keys = sorted(myDict) # sweet!
And BTW, Python 2 support means 2.7 - or do you care for older versions (I hope not)? |
Py2.7 is all I care about :-) Looks like this will be a handy alternative to 2to3: |
Thanks @peircej and @cbrnr for addressing this. Jon touched upon an issue that we need to consider when working on this project. The reality is that programming, while seemingly necessary, is not a compulsory requirement for undergraduate (and some graduate) psychology students in many universities. If they pick up any programming experience in graduate studies, its usually only enough to re-purpose some existing experiments (either an RA or past-colleague wrote) without understanding much about the underlying hardware. The average user of any stimulus generating software needs something that "just works" in most cases. I usually write compatible code out of habit. In fact, the stereoscopy libs should work with both versions (2.7 and 3.x). |
@peircej, python-future looks great, this could be the solution of choice! btw it's starting to become more and more difficult for me to use PsychoPy, as I sometimes require new features from other packages that are not available / not fully supported on Python 2 anymore. So for me, personally, the urgency of the conversion is increasing :) |
(In fact, I'm probably going to use expyriment for my next study for this reason) |
Ouch! ;-) OK, I'll try and spend some time on it this morning. I've tried to pull in some of @cbrnr commits but they break too much existing code. I think I'll have to use python-future instead and then use his commits (above) as a reference for when I hit problems |
Let me know if I can help. Most of the stuff I did after the script should also work after running python-future. One big issue will be the switch to wxPython 4 - I suggest that we don't try to maintain compatibility between both the old wxPython and Phoenix but focus on the latter. |
Sorry, but I'm going to disagree with you here. We should try and possibly find that we fail, in which case we give up. But generally this is going to be a matter of an import statement that has try...except at the top of the script. In my experience (supporting previous changes betwee wx versions) it isn't generally a big problem. Users don't like having to change their system, so we should try to be compatible with any version. |
I don't have experience with wxPython, but maybe the changes in 4.0.0 aren't that big. I'd just be careful not to try to support too much old stuff, at some point this will become unmanageable. E.g. will there be support for Python 2 and 3, wxPython 4 and <4, possibly PyQt and PySide (not to think about Qt 5 vs. Qt 4), etc. At some point users will need to start updating their systems if they want to continue to use a piece of software. IMHO. |
I've done this for a while now and in my experience it really isn't unmanageable. Yes, it sometimes means very slightly uglier code but I expect the (few dozen) developers to cope with that in order to save the (tens of thousands of) users some pain. |
OK, that's good to hear.
Here I'm going to disagree with you on both points 😄 .
Maybe it's no big deal most of the time, but if you have dozens of no big deals this still adds up. BTW, there's a package for abstracting various Qt versions: https://pypi.python.org/pypi/QtPy |
master branch is now pretty much compatible with all of py2/py3/wx3/wx4/qt4/qt5 Thanks for your help Clemens. Some of your changes I cherry-picked across but others were, at least, helpful in finding the issues. I'm sure there are still bugs to find but most of the demos appear to work and most of the windows in the app appear to load (and for py2 all tests still pass). If there are any doubts about how to keep things dual-compatible then just ask. |
@peircej, considering your last comment, will you be making a Python 3 release on PyPI? |
It will eventually be released on PyPI but not soon. For now I would not consider this safe for release until we've spent several months testing it |
OK, here we go. I ran
2to3
and added some manual edits so that the following simple example from the documentation already works (on my Mac):Eventually, this will hopefully fix #1061. Right now, we should probably ignore the GUI parts since these will likely require a lot of work.
I hope that this is a first step towards getting PsychoPy to run with Python 3. Note that it will probably be inconvenient to write code that is compatible with both 2 and 3, so I suggest that once everything runs in Python 3, development will switch to that version (and PsychoPy for Python 2 will remain available but not receive any further updates).
Let me know if this approach works for you. Since this is a big one, I hope that others will contribute as well. I guess all devs already have write access to my branch, I hope GitHub makes coordinating this straightforward (I have never done that before).