How can we make __future__ imports global?

前端 未结 2 389
-上瘾入骨i
-上瘾入骨i 2021-02-05 11:43

Specs: Python 2.7

I\'m working on a project that has several modules, I want to activate some features from the __future__ module in all of them. I would like to import

相关标签:
2条回答
  • 2021-02-05 12:23

    There's no way to do this in-language; you really can't make __future__ imports global in this sense. (Well, you probably can replace the normal import statements with something complicated around imp or something. See the Future statement documentation and scroll down to "Code compiled by…" But anything like this is almost certainly a bad idea.)

    The reason is that from __future__ import division isn't really a normal import. Or, rather, it's more than a normal import. You actually do get a name called division that you can inspect, but just having that value has no effect—so passing it to other modules doesn't affect those modules. On top of the normal import, Python has special magic that detects __future__ imports at the top of a module, or in the interactive interpreter, and changes the way your code is compiled. See future for the "real import" part, and Future statements for the "magic" part, if you want all the details.

    And there's no configuration file that lets you do this. But there is a command-line parameter:

    python -Qnew main.py
    

    This has the same effect as doing a from __future__ import division everywhere.

    You can add this to the #! lines, or alias pyfuturediv='python -Qnew' (or even alias python='python -Qnew') in your shell, or whatever, which maybe as good as a configuration file for your purposes.

    But really, if you want to make sure module B gets new-style division, you probably should have the __future__ declaration in B in the first place.

    Or, of course, you could just write for Python 3.0+ instead of 2.3-2.7. (Note that some of the core devs were against having command-line arguments, because "the right way to get feature X globally is to use a version of Python >= feature X's MandatoryRelease".) Or use // when you mean //.

    Another possibility is to use six, a module designed to let you write code that's almost Python 3.3 and have it work properly in 2.4-2.7 (and 3.0-3.2). For example, you don't get a print function, but you do get a print_ function that works exactly the same. You don't get Unicode literals, but you get u() fake literals—which, together with a UTF-8 encoding declaration in the source, is almost good enough. And it provides a whole lot of stuff that you can't get from __future__ as well—StringIO and BytesIO, exec as a function, the next function, etc.

    If the problem is that you have 1000 source files, and it's a pain to edit them all, you could use sed, or use 3to2 with just the option that fixes division, or…

    0 讨论(0)
  • 2021-02-05 12:42

    Another approach would be using isort. isort has a -a command line flag to add imports to files that you specify. Simply running isort without arguments will run it recursively on all python files in the current working directory and all subdirectories.

    If, like me, you have a virtual environment inside that folder, and are using git (or have an equivalent way of listing only your files) and don't want to run it on all files inside that virtual environment, you can use something like:

    git ls-tree -r HEAD --name-only | grep "\.py$" | xargs isort -a -y "from __future__ import division"

    0 讨论(0)
提交回复
热议问题