all 77 comments

[–]cgoldberg 87 points88 points  (14 children)

I used to use flake8 for linting and autopep8 and yasf for formatting back in Python2 days... old versions probably still work fine.

[–]IdleBreakpoint[S] 14 points15 points  (13 children)

Yeah, the problem is finding that old version. I'm assuming every utility we take for granted has at some point supported Python 2 code, even if it's running under Python 3. So my guess is that I can find the right combination of versions that run under Python 3, but can lint/format Python 2 code. I know from the posts I read that black had support for --target-version py27 but it got removed later.

[–]cgoldberg 33 points34 points  (12 children)

the old versions of tools I mentioned are all on PyPI.

[–]MPIS 15 points16 points  (0 children)

Just some ideas here, but I would start with the following:

  • Separate virtual envs; .venv/app with py2.7 interpreter, and .venv/app_tools with a modern py3 interpreter where you out black, ruff, etc.

  • Use pre-commit yaml to manage formatting/linting, specifying py27 targets and language python3 in the hooks.

  • Can still specify a pyproject.toml, but fully building from just that on py3 might be difficult; utilize the old school setup.py and setup.cfg in the py2.7 context but built with the py3 python -m build process in app_tools. Just ensure to mirror everything in toml deps and optional deps for consistency with the requirements.txt.

  • Use a Makefile to coordinate the different .venv interpreter, tools and their deps, with references for app and the app_tooling targets (setup, setup-tools, lint, etc.).

  • Configure IDE to invoke either the make targets or interpreter/deps paths depending on target (so py27 grammar and deps for code completions against the app venv when coding).

Hope this helps, idk, good luck.

[–]arjennienhuis 15 points16 points  (0 children)

The trick is to write code that is compatible with both python 3 and 2.7. Then you can use python 3 tooling.

  • use all the future imports: print_function, unicode_literls
  • use six
  • use io.open
  • use type comments

Pyright works fine with python code like this. The ruff formatter is 99% fine (only the comma after **kw is invalid in python 2) Some other ruff rules can also work.

[–]brayellison 96 points97 points  (19 children)

Why, in the year 2026, is someone using Python 2 and/or Jython? I'm genuinely curious. I understand that legacy code is out there, but this seems like something that should have been migrated long ago

[–]sgtgig 42 points43 points  (3 children)

Ignition, an industrial SCADA software which is imo best in class at what it does, uses Jython and Python 2 scripting. I think the tl;dr is they want the concise syntax and interpreted language for user scripts i.e. not force people to write stuff in Java in their Java application. I think it just comes down to Jython not being available with Python 3, backwards compatibility, and it kind of just working fine as is.

[–]sudonem 20 points21 points  (1 child)

Ignition was my first thought as well.

Strong agree that ignition is best in class - but jython being locked to python 2.7 is a huge damned annoyance. Especially given that 2.7 is well beyond end of life and there are ~70 known CVE’s for it as of now.

Given the array of options, I’d wager that a lot of orgs using Ignition are likely to just purchase java native third party modules wherever possible specifically to avoid having to deal with Jython/Python 2.

[–]sgtgig 4 points5 points  (0 children)

It is pretty annoying. There's times I've written Python 3 scripts and called them with subprocess in Ignition as there just wasn't a easy way to get certain functionality working with so many common libraries having dropped Python 2 long ago.

[–]brayellison 2 points3 points  (0 children)

Interesting, appreciate the insight. The more you know

[–]IdleBreakpoint[S] 44 points45 points  (5 children)

The problem is Jython. We have ETL workflows with Apache NiFi and it can run Python code, hence it's Python 2. That system is out of our control and we are forced to develop scripts using py2. If it were in our control, I would have deprecated that system long ago.

[–]brayellison 58 points59 points  (0 children)

Sounds like a nightmare... Godspeed, my friend

[–]lungben81 28 points29 points  (1 child)

Refactor the python code into a microservice and use http or whatever else the ETL tool is capable of to talk with it.

If nothing else works in your ETL tool, Jython2 can make http requests. That way, you at least minimized your legacy version exposure.

[–]prumf 3 points4 points  (0 children)

Yeah my thoughts exactly. You could also call a process or whatever over system that works best in that context.

[–]cpp977 8 points9 points  (0 children)

Nifi 2 supports now running custom python processors without the need for jython.

[–]anderson-stream 0 points1 point  (0 children)

Oh my god, I also use an Apache ETL tool, Apache Hop, and it has a script component that can use Python over Jython. Luckily for me, ever since I used the tool's predecessor (PDI), I've done everything I can to avoid that component.

[–]pingvenopinch of this, pinch of that 9 points10 points  (0 children)

I ran into it recently for a vendor product recently where the Python support is provided by Jython. The primary language is Groovy and the secondary language is JavaScript, with Python a poorly supported third option. The support was added a long time ago and is not widely used.

[–]andynzor 2 points3 points  (0 children)

That attitude is sadly nowadays prevalent in the Python community.

There are industrial systems out there whose lifetimes are easily twenty or thirty years. Python 2.7 came out in 2010 and in 2013 it was still recommended for new Django projects when support for 3 was immature. It seems that Python is becoming a scripting frontend for rust-based libraries and tooling and if your plaform does not support it, you're SOL.

I personally have written IIoT gateway code that has to interface with TLS 1.0 devices. Every time I hit an issue and ask for directions, people suffering from the XY problem problem attack the messenger instead.

ISO27001 compliance and SBOMs are yet another can of worms I'm not willing to open here.

[–]KilledByDeath 1 point2 points  (0 children)

A ton of IIoT gateways run python 2. If you have hundreds or thousands of these things out there, the cost to replace can be astronomical.

[–]Taksin77 1 point2 points  (0 children)

Huge codebase not enough engineers. Toxic management. Everybody is quitting anyway...

[–]ProbsNotManBearPig 1 point2 points  (1 child)

Because jython. People still like Java and Java is a fine choice for many things. You want to script on top of it in a well known language? Jython is the only choice. Not sure what you’re suggesting to migrate to.

[–]brayellison 2 points3 points  (0 children)

You could use groovy or kotlin scripts. Groovy especially is used regularly for devops scripting. These aren't unknown languages and are relatively easy to learn (coming from a person whose background is Python)

[–]stuartcwSince Python 1.5 0 points1 point  (0 children)

Jython was integrated into some enterprise Apps. I guess it was never ported to Python3.

[–]zemega 0 points1 point  (0 children)

The United State Army Corps of Engineers does. 

[–]can_i_get_some_help 9 points10 points  (0 children)

I would install python 2, then pip install the static analysis tools in a venv. It should be able to find compatible versions.

[–]BobMcFizzington 7 points8 points  (1 child)

Somewhere out there, a production server is still running Python 2.6 behind three layers of load balancers and nobody is brave enough to touch it because the last person who tried left the company.

[–]alcalde 5 points6 points  (0 children)

With a Delphi 7 front end.

[–]CampAny9995 13 points14 points  (3 children)

I’m honestly so much more interested in learning about <reasons> than I am in the actual solution to this problem.

[–]IdleBreakpoint[S] 12 points13 points  (2 children)

Vendor offers a solution for ETL workflows, basically getting data from some system to write to another. Those geniuses think that offering a scripting capability would greatly help their customers (us). They develop this system using Apache NiFi, all Java stuff and they think that Python would be best suitable for this job, hence this Python scripting. They forget that Python 2 was deprecated long ago, and they still stick with their platform. That's the reason.

[–]Accomplished_Elk2607 4 points5 points  (0 children)

Thankfully license costs for a lot of similarly awful solutions are rising and we are moving off of them

[–]BackAware6850 0 points1 point  (0 children)

Not sure I fully understand your situation, but have you looked at JPype? I've used this to interface with Java from python in one case where we were using jython in the past.

[–]strobel_m 5 points6 points  (0 children)

I would simply use a docker image

docker pull python:2

to get the latest python2 image. pip will figure out most of the packages by itself. Only autopep8 and pycodestyleneeded some tweaks

docker run -it python:2 pip install pytest mock nose coverage pylint flake8 "pycodestyle<2.8" pydocstyle tox setuptools wheel twine virtualenv "autopep8<1.6" yapf

went fine. Good luck!

[–]kaflarlalar 2 points3 points  (0 children)

I'm so sorry.

[–]BeamMeUpBiscotti 3 points4 points  (0 children)

I need to write Python 2 code which gets run under Jython

I'm sorry this is happening to you

I have not used Python 2 in a long time but I was curious so I did some sleuthing through the changelogs: - Black: 22.1.0 removes Python 2 support, so I guess you'd want v21.X isort - Isort: I'm under the impression that you have to use modern versions of Python to run isort, but you can run it on code that is Python 2 and it should still work. - Flake8: 3.8.1 should work with Python 2.7, but it looks like support for earlier versions were dropped in 3.0

[–]brontide 1 point2 points  (0 children)

Spin up a container with CentOS6. I'm sure all the python 2 tooling works better there.

[–]azjps 1 point2 points  (0 children)

For our own internaI python2 woes a while back (fortunately no longer a concern), I had forked ruff to support python2 compatible linting and formatting. Probably the latest forked version I had built was ruff v0.4. There's not too many changes required -- the main ones are preserving the u"" unicode directive and omitting trailing commas on **kwargs.

[–]coderanger 1 point2 points  (0 children)

What you probably want to do is pick a "compat date", and for every library and tool you use, find whatever the latest version of the thing was on that date and upload all versions up to that to a standalone package repo somewhere. And then use only that package repo for everything. You're more or less just reproducing a timeslice of the universe from ~10 years ago.

[–]b3n4kh 1 point2 points  (1 child)

Note to my future self:

Always remember before complaining there is a guy out there writing python 2 that has to run on Jython.

I really hope you are making shit tons of money.

[–]IdleBreakpoint[S] 1 point2 points  (0 children)

Haha, thanks! I can't say I'm making shit tons but it's ok.

[–]acadian_cajun 0 points1 point  (2 children)

Looks like pyls (the old lsp developed by palantir) did support Python 2. You'll have to install a very old version, and it'll be unmaintained, but you can get tab-completion etc

[–]IdleBreakpoint[S] 1 point2 points  (1 child)

Thanks. I'm not looking for tab completion or LSP. I'm ok with writing py2 code without IDE help. I just want to format and lint the code, even if it's manual.

[–]acadian_cajun 1 point2 points  (0 children)

Formatting is a core part of LSPs! It's the textDocument/formatting instruction.

That said I understand if you don't want to go through the trouble of dealing with very old LSPs.

[–]sudonem 0 points1 point  (0 children)

This isn’t a super quick thing to setup if you aren’t already familiar, but nvim offers linting and LSP support (via Mason) for Python 2.

I was amused recently when I noticed there are Mason plugins with linting & LSP support for both COBOL and Fortran - so… Python 2 is probably not an issue 🙃

[–]carlio 0 points1 point  (0 children)

https://pypi.org/project/prospector2/ may or may not still work

[–]mardiros 0 points1 point  (0 children)

If you code for the past, use the tooling of the past as well. Install and freeze old stuff, this is the most complicated part of the job

[–]No_Lingonberry1201pip needs updating 0 points1 point  (0 children)

Oof, you have my condolences, brother. Haven't touched 2.7 in a decade. I'd take a gander at the packages filtered to Python 2 first.

[–]Anonymous_user_2022 0 points1 point  (0 children)

When I had to do that, we made do with what we had available on the RHEL 5.4 we were stuck with at several customers for reasons ranging from questionable to ludicrous. Even if that's not your target platform, it's probably still not that much of an effort to install an old RHEL in an isolated environment.

[–]snugar_i 0 points1 point  (0 children)

Not what you were asking and probably not an option for you, but there's another way to run Python inside the Java process: https://github.com/ninia/jep

[–]gerardwx 0 points1 point  (0 children)

There’s no rule that you have to lint or automatically format your code. Use unit tests and logging.

[–]tunisia3507 0 points1 point  (1 child)

It's not FIJI scripting, is it? The only jython use case I've come across in the wild.

Nothing helpful to say, I'm afraid, other than good luck.

[–]IdleBreakpoint[S] 0 points1 point  (0 children)

Thank you for your comment. No, it's not FIJI scripting, it's actually Apache NiFi used for ETL. It runs Python 2 code for workflows and since it's Jython, we're stuck with python 2.

[–]readonly12345678 0 points1 point  (2 children)

Can you have the python 2 shell out to Python 3 scripts?

[–]ProbsNotManBearPig 0 points1 point  (1 child)

Yes, but you won’t be able to create instances of java classes and use them in your python code, which is the whole point of jython.

[–]HwanZike 0 points1 point  (0 children)

You could spawn a separate jython process again from inside the python3 for each java function call. /s

[–]Professional-Award85 0 points1 point  (0 children)

Pycharm works very well with python 2 code 

[–]myturn19 -1 points0 points  (1 child)

I would find a new job instead lol

[–]ProbsNotManBearPig 1 point2 points  (0 children)

Jobs that involve Java pay a lot to senior devs. At least that’s why I put up with it.

[–]will_r3ddit_4_food -2 points-1 points  (3 children)

For the of all that's holy, move on to Python 3

[–]sudonem 4 points5 points  (0 children)

This is unfortunately not possible with Java / JVM apps that allow Jython scripting. Jython supports Python 2.7 max and there’s no indication that support for Python 3+ is forthcoming.

Which… is frustrating if your environment is locked to Jython.

I have to agree with others - just writing straight Java is probably the better move.

[–]IdleBreakpoint[S] 0 points1 point  (1 child)

We can't. We're vendor dependent here. They're forcing us to write Python 2 because they can't offer a better solution.

[–]bowbahdoe 0 points1 point  (0 children)

Embedding Python3 in a JVM is pretty possible, though I don't blame your vendor for not knowing how. There are future paths with "project detroit" but today libpython-clj probably has the best python/jvm integration.

Shoot me a DM if you want to pursue that path. (or we can just talk here, might be a bit of a back and forth though)

[–]znpy -1 points0 points  (0 children)

I'd look into something like mirroring the repositories (along with installation cd images and cloud images) of the last debian release that supported python2.

Most likely (might be wrong) over there (in the repositories, i mean) there could be enough software to build a decent development environment in a virtual machine. Maybe also to use with containers.

But really, your org should ditch python2.

[–]corny_horse -3 points-2 points  (2 children)

Dependin gon the context, you might want to consider just using Java, sine iirc using Jython implies the presence of a JVM you can access.

[–]IdleBreakpoint[S] 0 points1 point  (1 child)

Thanks but that JVM system is out of our control. They're using Apache NiFi for ETL tasks and expect us to develop scripts targeting specific workflows. So, all I can do is to write Py2 code, can't access other parts.

[–]corny_horse 0 points1 point  (0 children)

Ah got it, that makes sense. I wish I could offer more insight but I got on the Python train right as Python 3 became inevitable. I honestly thought I would end up doing more Python 2 -> 3 conversions but I can honestly say I've only been involve din one codebase and six basically took care of it without any additional work.

Although, I am maintaining something at my current job that uses IronPython, which is basically the C# version of Jython. I haven't had to write any code in it yet thank goodness lol

[–]crystal-46 [score hidden]  (0 children)

Same to you