Live data from Hacker News

Say “no” to import side‐effects in Python

chrismorgan.info

71–80 of 86 posts

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

#71
post #47

Earlier quoted context omitted.

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.

This isn't a good solution. I pip install mysql-python several times a week on my mac ( I use different venv's for different branches and we have several different services that I work on in a given week, thus I'm installing packages via pip A LOT) and we always install it in a venv. Sure it can be a bit of a pain but it's well worth it IMO.

Our steps to always get it working: make sure mysql_config is in your path env variable, make sure the xcode command line tools are probably installed, and make sure the mysql command line client is setup and working correctly locally. Past that is just works for us on Mac OS X 10.7+. I think 10.6 and earlier also work but I'm not sure.

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

#72
If there's one thing I've learned from working with old PHP codebases, it's that side-effects from include/require are a horrible horrible idea.

I'm OK with Java's static-initializers, but that's because they've got a whole bunch of rules around them preventing common kinds of abuse.

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

#73

This in no way invalidates the point of the post, but I can't imagine going back to installing everything globally instead of using virtualenv. If you do that, at least you won't have every package you every looked at in your path.

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

Almost all the awkward modules I've come across work when you use --system-site-packages

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

#74
post #64
post #57

Earlier quoted context omitted.

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.

That is true, and unfortunately I have used Python only sparingly until now, and have no experience using PyGtk at all.

I took a quick look at PyGObject[0] (unsure if that is what one would actually use for this), and the most helpful part seems to be [1], giving some hints on extending GObject.Object, which should be translatable to extending other existing GObject type classes.

As for porting, I agree that can be a pain in that case. When bindings move from a manual implementation to inflating it from an external description. You often end up with good tutorials for the first, and good API reference for the second. If I need to understand other kinds of Gtk bindings, I search for examples on custom TreeModels or other potentially messy things like that to get a feel for it.

[0] https://wiki.gnome.org/action/show/Projects/PyGObject?action... [1] http://python-gtk-3-tutorial.readthedocs.org/en/latest/objec...

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

#75

Earlier quoted context omitted.

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.

That's interesting. I can see the motivation... it's helpful to have modules come into the world fully initialized, and initialization often involves side effects.

Is Rust going to allow side effects on initialization?

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

#76

I do most of my work with Perl, rather than Python, but in Perl there are several kinds of stock import-level side-effects which are actually quite helpful. These are pretty light-weight though. They boil down to: 1. Global lexical changes to Perl. Sometimes this is the whole point of an import (for example Carp::Always, which typically turns any warning or exception string into a full stack dump). I can't imagine do…

Technically in Perl, a "use" statement is asking for those manipulations, though. If you want to just load the library but not ask for any of those things, you would require the library, either in or not in a BEGIN block depending on your desires. If, however, merely "require"ing the library performed any of those manipulations, that would be a violation of what I'd expect. (Of course, if the sole purpose of your module is to perform those manipulations, "require" may not do anything useful, but I'd still expect it not to do anything to my local namespace, either.)

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

#77

Earlier quoted context omitted.

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

I was referring more to Haskell's lack of side effects. I don't think you can do this in modules.

You can, with unsafePerformIO. Unlike many instances where we can just wave away unsafePerformIO and declare it's an exception that you'll probably never encounter unless you ask for it, this is one instance you may encounter "in the wild" that may not be entirely safe, or may introduce a global scope where you weren't necessarily expecting one. In particular, this usually takes the form of creating a Reference of some kind at initialization time (IORef, STM TVar, etc).

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

#78

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 u…

You should use a factory pattern, like this: [...] 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: [...] Instead, hook up views inside your app factory: [...]

That’s basically what I did on my second iteration. It is an improvement in some respects, particularly breaking the circular dependencies caused by using the decorators on the global application singleton. On the other hand, now you need some variation of God Object that not only imports all your modules that used to have decorators but also knows enough about their internal implementation to set up the routes and things like pre- and post-request logic directly on the application object you get back from the factory.

The next logical step after that then seemed to be having each module/package that contains views or similar logic provide some sort of initialization function that is declared when you import the module and takes an application object as a parameter. Then we can use app.add_url_rule and friends to wire up the various handlers within each package/module but decoupled from any sort of global application object that needs the circular import. This is the tidiest style I’ve found so far, and all my Flask projects in recent years have used something broadly like it. It does only require one import followed by one initialization call for each package/module, which logically seems to be as good as we can get, given that our starting point is a desire to avoid including any initialization implicitly within the import itself and to avoid depending on global singletons.

Somehow, it still doesn’t quite feel right for some reason. I think it’s because even with that general design, I’ve still got a recurring pattern in each of how I create these modules and how I import and then initialize them. My instinct says we ought not to need that extra boilerplate in a highly dynamic language like Python, but I’ve yet to find any alternative that is neater in general. At least in the most simple cases this only adds a couple of extra lines (converting the decorators to an init function in each package/module, and then calling that function at the top level after importing the package/module), which is clearly better than the earlier, more highly connected designs.

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

#79
post #49

Earlier quoted context omitted.

I haven't grown out of metaprogramming at all. I just try and use it only when it's the best option. Usually because it means reducing duplication. I liked metaprogramming to an extent in C++. I _love_ it in D.

Replace "best option" with "only practical option" and you're good to go.

That may depend on the language you are using.

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

#80
I am an author of a library [1] that does this. I understand the what the OP is talking about and agree with it, but like anything for me the rule is "(1) Don't do dangerous behavior X. (2) If you are an expert, do dangerous behavior X sparingly and with caution."

Mind you, my library does not connect to a database, or any such crazy thing. It simply creates a singleton which is then useful throughout your application. There would be very few cases where you would not want that singleton and you would want your own instance. If so, you are free to completely ignore the created singleton and make your own instance. The creation process is also idempotent, except the data you put into that singleton; that data is a special case: it is your explicit responsibility to namespace it, which is indeed the whole point of this library. I feel pretty good about this thing.

[1] https://github.com/ipartola/groper

Post reply on HN