Live data from Hacker News

Say “no” to import side‐effects in Python

chrismorgan.info

61–70 of 86 posts

Re: Say “no” to import side‐effects in Python

#61
post #47

Earlier quoted context omitted.

I just can't get to use some modules within virtualenv. They seem to create more problems than using systemwide.

Which ones? You can get some help. Learning virtualenv is a smart long-term move

If you're on a Mac, good luck getting pip to install mysql-python. I use Macports for that.

Re: Say “no” to import side‐effects in Python

#62
post #47

Earlier quoted context omitted.

I just can't get to use some modules within virtualenv. They seem to create more problems than using systemwide.

Which ones? You can get some help. Learning virtualenv is a smart long-term move

This. We've all wrestled with problem modules. Qt comes to mind for me. StackOverflow has always been helpful I've never seriously considered ditching venv.

Re: Say “no” to import side‐effects in Python

#63
post #31

Earlier quoted context omitted.

from __future__ import print_function

That's a side effect, right? Your module after the import is not the same as it was before, or am I missing something?

Future imports are not imports at all (the fact that they use the same syntax as imports is misleading IMO). They are tags that instruct the interpreter to turn on certain features only when interpreting the given file. They must appear before any statements in the file, and they take effect before interpretation of the file starts. You could argue that this constitutes an import side effect, but that's neither here nor there, and not helpful.

Re: Say “no” to import side‐effects in Python

#64
post #57
post #42

Earlier quoted context omitted.

Not me either anymore. I tried to port to introspection + Gtk3 but ran into problems with widget subclasses and no documentation to resolve it with.

I only extensively used it from Perl and Vala, but with GObject-Introspection I tend to more often look at the original library documentation than something language specific. This can be a disadvantage at first, but for me it turned out more convenient, since GIR-inflated bindings can be more complete, as long as the inflation supports the features the API describes. They also tend to be more consistent in their dif…

well it doesn't really explain how to port from pygtk or how python classes interact with g-i.

Re: Say “no” to import side‐effects in Python

#65
post #10

Earlier quoted context omitted.

> I once used a Ruby library that, when loaded, would try to connect to a database on a remote machine. How is that at all acceptable? I can't believe that a library that phones home would gain any sort of popularity. I can't say I know much of anything about the Ruby community, but if they've conditioned you to jump through hoops like importing modules at specific times to avoid delays, that is a serious problem. Co…

install my module! Also.. trust me because it's totally safe. curl http://foo.com/tBrwn | bash http://rvm.io/rvm/install

Out of curiosity, what would be better to handle the case of RVM?

It's explicitly user space software, and unprivileged user space software at that, so having it require admin interaction (i.e. touching the system package manager) to install seems like a sledgehammer where a flyswatter would do.

They could use a VCS repo of some kind, but that doesn't handle the various folder and script installs that need to happen - and also doesn't help if there isn't that specific VCS on the system.

Upstream security is less of a concern since that hotlink just points to raw code on Github, and over HTTPS no less.

So what are the negatives here? For software like RVM, this seems like the best, most portable solution that works for the most people.

Re: Say “no” to import side‐effects in Python

#66
Putting side effects in the __init__ code seems to become quite fashionable these days but is a pretty bad idea since it removes the possibility to "just" import the functionality defined by the module without performing any initialization. Personally, I always try to avoid having a system that relies on some global configuration (like e.g. Django, Matplotlib or Flask do). In matplotlib for example this causes a lot of problems, since importing the pylab module will automatically (among other things) load and initialize a backend, which is then set in stone for the rest of the session.

IMHO, the way to go here instead is dependency injection:

Inject the configuration into the module through a function or class method (e.g. Flask.initialize({config state}). Wrapping all module functionality that depends on configuration in a class is a good idea here since it allows you to use multiple configurations in parallel and makes your code more modular.

As an example, in BlitzDB (a document-oriented database for Python, https://github.com/adewes/blitzdb) there is no global configuration at all, so you can initialize and use multiple backends in parallel as you please without worrying about side effects. SQLAlchemy does it in a similar way btw.

Re: Say “no” to import side‐effects in Python

#67

Would anyone like to share their experiences avoiding this sort of problem in the context of web frameworks and building the back end for larger web sites/apps? As an example for discussion, the first time I wrote a Flask-based back-end, I backed myself into a corner almost immediately in the following way. Firstly, the WSGI file that the web server uses to start the application followed the suggestion in the Flask d…

The example on the Flask tutorial with the app at module level is really only viable if you cram everything inside one module, it gets old soon. You should use a factory pattern, like this:

    def app_factory(config):
        app = Flask("yourapplication")
        app.config.from_pyfile(config)
        # ...
        return app
Then whenever you need access to your app object, you use the provided proxy:

    from flask import current_app as app
You can't use it at module level though (because there isn't an application context setup by that time), so this doesn't work:

    @app.route('/')
    def home_page():
        # ...
Instead, hook up views inside your app factory:

    def app_factory(config):
        # ...
        app.route('/')(somemodule.home_page)
        # ...
For the test suite, you can now instantiate apps with a different configuration:

    from flask import current_app as app
    from myfoo import app_factory
    import unittest

    class MyFooTest(unittest.TestCase):
        # ...

    if __name__ == '__main__'
        test_app = app_factory(test_config)
        # The app proxy will point to that inside test cases
        unittest.main()

TL;DR: The factory pattern is your friend. Parametrize all the things. Avoid singletons at module level, this leads to spaghetti. If you need convenience, create proxies.

Re: Say “no” to import side‐effects in Python

#68

This is one reason why I prefer Haskell ;)

I think most statically typed languages don't care for this kind of shenanigans.

In addition to the many other languages listed here, Go allows side effects on import.

Re: Say “no” to import side‐effects in Python

#69

Putting side effects in the __init__ code seems to become quite fashionable these days but is a pretty bad idea since it removes the possibility to "just" import the functionality defined by the module without performing any initialization. Personally, I always try to avoid having a system that relies on some global configuration (like e.g. Django, Matplotlib or Flask do). In matplotlib for example this causes a lot…

FYI, it is possible to call Matplotlib in an 'object-oriented' way without global state; though it's a bit more cumbersome than just using the pylab interface. See http://matplotlib.org/examples/pylab_examples/webapp_demo.ht... for an example.

Re: Say “no” to import side‐effects in Python

#70
post #35
post #31

Earlier quoted context omitted.

from __future__ import print_function

As I understand it, "from __future__ import ..." statements are actually a special type of statement that doesn't actually import a module at all - they just use similar syntax for compatibility reasons. There is an actual __future__ module, also for compatibility reasons, but importing it has no side-effects.

Whether they import a module or not is - IMO - irrelevant. I was responding to this claim: In Python, side-effects are simply not acceptable at all. One should instead put the code with the side-effect in a function and call it. `__future__` imports are obviously and purposefully side-effectful, there's no `print_function()`.
Post reply on HN