14

For those unfamiliar with ~/.bashrc, it is a customizable script that exists for the Unix shell Bash. When a new terminal session begins, this user-specific file is run. Users can script common variables, functions, and environment settings in this file and thus have them automatically loaded whenever they open a terminal window.

Does something analogous exist for Python? Essentially I would like to define a handful of global Python functions in a script and ensure that they are loaded whenever I run a Python script on my machine, or whenever I start a Python terminal. I am wondering if this behavior already exists, or if there is a straight-forward way to implement it.

Community
  • 1
  • 1
Jake
  • 7,565
  • 6
  • 55
  • 68
  • See [`__init__.py`](http://stackoverflow.com/questions/448271/what-is-init-py-for). – e0k Jan 30 '16 at 05:26
  • 5
    Running for every Python script isn't a supported behavior (`__init__.py` can be used to ensure certain code is run if a package or its children are imported though), but for customizing the interactive interpreter, set the `PYTHONSTARTUP` environment variable to point to a file with Python commands to run before handing off to the interactive interpreter, e.g. `export PYTHONSTARTUP=$HOME/.pythonrc`. – ShadowRanger Jan 30 '16 at 05:29
  • 1
    See https://docs.python.org/2/library/site.html – Charles Duffy Jan 30 '16 at 05:35
  • 1
    ok write all your functions and put it in `/usr/lib/pythonX.y/dist-packages` import it when you need them. Simple! – Ja8zyjits Jan 30 '16 at 05:35
  • @ShadowRanger That is exactly what I was looking for. Make this an answer and I'll accept. – Jake Jan 30 '16 at 05:54

3 Answers3

8

Running for every Python script isn't a good idea since it breaks namespacing; per Zen of Python:

Namespaces are one honking great idea -- let's do more of those!

That said, __init__.py can be used to ensure certain code is run if a package or its children are imported, and for customizing the interactive interpreter, set the PYTHONSTARTUP environment variable to point to a file with Python commands to run before handing off to the interactive interpreter, e.g. export PYTHONSTARTUP=$HOME/.pythonrc.

Just make sure the PYTHONSTARTUP file contains legal syntax for both Py2 and Py3 because there is no PYTHON3STARTUP, it'll be run for both versions of Python.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
  • This syntax `cls = lambda: print("\033c\033[3J", end='')` for example is recognized only by python3. For avoid this is possible doing: `from __future__ import print_function` `cls = lambda: print("\033c\033[3J", end='')` `cls()` – Mario Palumbo Dec 23 '20 at 12:06
6

This is a bad idea -- don't do it. Really. (Namespace pollution is a serious problem, and you do nobody any favors by writing code that only works on your own machines and nowhere else; by contrast, if you package up your code in a module, you can publish and distribute it properly).

However, if you insist, see the site module, and particular its user-customization behavior:

After this, an attempt is made to import a module named usercustomize, which can perform arbitrary user-specific customizations, if ENABLE_USER_SITE is true. This file is intended to be created in the user site-packages directory (see below), which is part of sys.path unless disabled by -s. An ImportError will be silently ignored.

Thus, you can create a usercustomize module that hotpatches to your heart's content.


As an example of such hotpatching:

def myfunc():
  print 'hello'

main_ns = __import__('__main__')
main_ns.myfunc = myfunc
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • um! what if there are some short system specific functions like some batch commands,still bad? – Ja8zyjits Jan 30 '16 at 05:40
  • Short form: Yes, bad. "Explicit is better than implicit" is part of the Python Way -- if you're using something local, it should be explicit that you are rather than implicitly present in every namespace. – Charles Duffy Jan 30 '16 at 05:42
  • 1
    ...if you want something that's just an extension to the local shell, maybe use IPython and its extension mechanism? That way you're at least not meddling with the behavior of scripts. See http://ipython.readthedocs.org/en/stable/config/extensions/index.html – Charles Duffy Jan 30 '16 at 05:42
  • I'm not clear on how this is supposed to work. For instance, I added `usercustomize.py` to `/usr/lib/python2.7/dist-packages` with the function `def test_function(): pass`. I ensured that `site.ENABLE_USER_SITE == True`. However, calling `test_function()` yields a `NameError`, indicating that the script is never run. – Jake Jan 30 '16 at 06:02
  • @Jake, just because it's imported doesn't mean that it's in your default namespace by magic; however, it *does* give you a platform from which to hotpatch, so you can (for instance) directly reach into and modify the `__main__` namespace (which is default for interactive shells). I've edited a demonstration in. – Charles Duffy Jan 30 '16 at 14:40
6

Essentially I would like to define a handful of global Python functions in a script and ensure that they are loaded whenever I run a python script on my machine, or whenever I start a Python terminal

Let's talk about your second option. There are ways to load functions and variables when you start a terminal. I'd recommend using IPython instead of the default Python terminal. However, to do this without installing IPython, modify the environment variable PYTHONSTARTUP. You do lose the ability to compartmentalize your config files.

Once you install IPython, you'll need to initialize its configuration files. To create the default profile:

ipython profile create 

To address the common topic in the other answers, global variables and functions are a bad idea especially if they're implicitly defined. However, you can define and load separate config files when starting ipython. To create such a profile:

ipython profile create <name>

To load the <name> profile:

ipython --profile=<name>

Now to modify the config files. Run this command to see where they are:

ipython locate profile

You should find ipython_config.py. I'd suggest reading it, it has very helpful comments.

But to get to the point, you can load arbitrary functions and variables when starting ipython by adding these lines to the config file:

c.InteractiveShellApp.exec_lines = [ "def p(s): print s" ]
c.InteractiveShellApp.exec_files = [ "/path/of/script.py" ] 

I'm referencing the IPython docs and the comments in ipython_config.py:

96  # List of files to run at IPython startup.                                      
97  # c.TerminalIPythonApp.exec_files = []                                          
98                                                                                 
99  # lines of code to run at IPython startup.                                      
100 # c.TerminalIPythonApp.exec_lines = []
Mr Lister
  • 45,515
  • 15
  • 108
  • 150
Hugo O. Rivera
  • 651
  • 4
  • 11