Way to run all packages I want in python script - python

There are many times that I want to use same packages in my scripts, I mostly copy paste packages I want from my last script. I want to stop this work and run all of theme with one simple function, Today i try this:
def econometrics():
print("Econometrics is starting")
import pandas as pd
import numpy as np
import statsmodels.formula.api as smf
import statsmodels.api as sm
import matplotlib.pyplot as plt
print("Econometrics is started")
econometrics()
the function runs without error but when I call some method from packages, I get errors like this:
name 'plt' is not defined
What is wrong with that code? is there anyway to define function to do that?

What is wrong with that code?
Simple answer: Variable scope. plt (and the others) are only accessible from within the econometrics method.
Try making one file, named importer.py, for example
import pandas as pd
import numpy as np
import statsmodels.formula.api as smf
import statsmodels.api as sm
import matplotlib.pyplot as plt
Then in your other code (that is in the same directory),
from importer import *
Using an __init__.py is probably the recommended way to approach that, though, but it wasn't clear if you have a module/package layout, or not.
If you do, then use
Relative import (same directory): from . import *
Absolute import (use module name): from some_module import *

Your intent is wrong in python's grammar. Because within your code, the variables range are scoped within the function. So, when you do your imports, you're creating a bunch of variables within the econometrics function range, and thus your variables are only in reach within that function.
So, let's take a simpler example:
>>> def foobar():
... a = 1
... b = 2
...
>>> foobar()
>>> a
NameError: name 'a' is not defined
here a and b only exist within foobar's function scope, so it's out of scope at the main scope.
To do what you want, the way you want it, you should declare your variable as belonging to the global scope:
def econometrics():
global pd, np, smf, sm, plt
print("Econometrics is starting")
import pandas as pd
import numpy as np
import statsmodels.formula.api as smf
import statsmodels.api as sm
import matplotlib.pyplot as plt
print("Econometrics is started")
econometrics()
So to get back to the foobar example:
>>> def foobar():
... global a, b
... a = 1
... b = 2
...
>>> foobar()
>>> a
1
>>> b
2
Though, I do not really like that way of doing things, as it's doing things implicitely. Considering you have a python module with just the econometrics function defined, people reading the following code:
from econometrics import econometrics
econometrics()
plt.something()
wouldn't necessary understand that plt has been made available through the econometrics function call. Adding a comment would help, but still is an unnecessary extra step.
Generally speaking, doing globals within any language is wrong, and there's most of the time always a better way to do it. Within the "Zen of python", it is stated that "Explicit is better than implicit", so I believe a more elegant way would be to create a module that does the import, and then you'd import what you need from the module:
econometrics.py:
import pandas as pd
import numpy as np
import statsmodels.formula.api as smf
import statsmodels.api as sm
import matplotlib.pyplot as plt
and in your code you'd then import only what you need:
from econometrics import pd, plt
plt.something()
which would be much more elegant and explicit! Then, you'd just have to drop that file in any projects you need your mathematics modules to have all your beloved modules that need - and only them - available in your code!
Then as a step further, you could define your own python module, with a full blown setup.py, and with your econometrics.py file being a __init__.py in the econometrics package directory, to then have it installed as a python package through:
python setup.py install
at the root of your sources. So then any code you work out can be using econometrics as a python package. You might even consider making it a package on pypi!
HTH

You imported the packages into the scope of the function. If you want to use them in the global scope, you have to tell python
def importfunc():
global np
import numpy as np
importfunc()
print np.version.version
On a side note: Are you using some kind of toolchain? I'd think it would be better to use an IDE or to write a script which sets up new projects for you.

The various imports are performed when you call the function, but the names pd, np, etc are local to the function, so they can't be referenced outside the function.
I suppose you could return those names, but importing modules in a function like that makes your code a little harder for readers to follow, IMHO.

Related

Python - Importing packages by running a script

I have a script which is importing lots of packages, including import numpy as np.
I have lots of scripts which need to import all of these packages (including some of my own). To make my life easier, I have a file called mysetup.py in my path to import all the packages. It includes the statement in a function called "import numpy as np".
I run "main.py". It runs the following
from mysetup import *
import_my_stuff()
np.pi()
"mysetup.py"
def import_my_stuff():
import numpy as np
return
However, I am unable to use numpy in "main.py" - this code will fail. Any suggestions as to why?
The problem you are facing is a consequence of a very important features of Python: namespaces.
https://docs.python.org/3/tutorial/classes.html#python-scopes-and-namespaces
https://realpython.com/python-namespaces-scope/
Basically, in your case, when you do that (numpy) import inside the (import_my_stuff) function, you are defining the code object numpy/np inside the function namespace. (scope, if you prefer).
To solve your issue (the way you are doing; not the only way), you should simply import everything at the module top level (without a function encapsulating the imports):
mysetup.py:
import numpy as np
# other modules...
main.py:
from mysetup import *
np.pi()
Imports in functions are not the best idea.
But you can just define whatever imports you need in top level code of mysetup.py
import numpy as np
and then it will be available when you import * from mysetup
from mysetup import *
print(np.pi)

how to only import module if necessary and only once

I have a class which can be plotted using matplotlib, but it can (and will) also be used without plotting it.
I would like to only import matplotlib if necessary, ie. if the plot method is called on an instance of the class, but at the same time I would like to only import matplotlib once if at all.
Currently what I do is:
class Cheese:
def plot(self):
from matplotlib import pyplot as plt
# *plot some cheese*
..but I suppose that this may lead to importing multiple times.
I can think of lots of ways to accomplish only importing once, but they are not pretty.
What is a pretty and "pythonic" way of doing this?
I don't mean for this to be "opinion based", so let me clarify what I mean by "pretty":
using the fewest lines of code.
most readable
most efficient
least error-prone
etc.
If a module is already loaded then it won't be loaded again. you will just get a reference to it. If you don't plan to use this class locally and just want to satisfy the typehinter then you can do the following
#imports
#import whatever you need localy
from typing import TYPE_CHECKING
if TYPE_CHECKING: # False at runtime
from matplotlib import pyplot as plt
Optional import in Python:
try:
import something
import_something = True
except ImportError:
import something_else
import_something_else = True
Conditional import in Python:
if condition:
import something
# something library related code
elif condition:
# code without library
import related to one function:
def foo():
import some_library_to_use_only_inside_foo
TLDR; Python does so for you already, for free.
Python import machinery imports module only once, even if it was imported multiple times. Even from different files (docs).
The most pythonic way to import something is to do so at the beginning of file. Unless you have special needs, like import different modules depending on some condition, eg. platform (windows, linux).

Importing names from another python file

I've tried searching with Google and in stackoverflow, but I can't find the answer to this simple question, that has probably been asked many times before
In file f1.py, I have
import numpy as np
In file f2.py, I have
import f1
class One:
mat = np.array([[1]]))
When I run f2, I get the error message that 'np' is undefined. How should I express my obvious intentions?
To give background, I am writing my first python3 program that is not a toy program. f1 represents the substantial code. f2 is supposed to be a unittest program. However, some fundamental misunderstanding of python syntax is preventing me from making progress. I thought that the import of f1 would bring np into the namespace of f2, but it doesn't seem to.
I thought that the import of f1 would bring np into the namespace of f2, but it doesn't seem to.
Indeed. Each module has it's own namespace, and you have to explicitely import all modules you depend on. So if f2.py needs numpy, it has to explicitely import it:
import numpy as np
import f1
class One:
mat = np.array([[1]]))
NB : importing f1 doesn't directly injects any other name defined in f1 either, so if you have a function "foo" in f1, in f2 you'll need to either import f1 (as in the above example) and use the qualified name f1.foo() or explicitely import name "foo", ie from f1 import foo (but then you'll only get access to foo, not any of the other names defined in f1).
mat = np.array([[1]])
In this line the np is not in local namespace because you have not imported np in local namespace.
So if you have to use np you should use following line:-
mat = f1.np.array([[1]])
For more info go to this link import x and from x import
You should import np like this:
from f1 import np

How to share imports between modules?

My package looks like this:
These helpers, since they are all dealing with scipy, all have common imports:
from matplotlib import pyplot as plt
import numpy as np
I'm wondering if it is possible to extract them out, and put it somewhere else, so I can reduce the duplicate code within each module?
You can create a file called my_imports.py which does all your imports and makes them available as * via the __all__ variable (note that the module names are declared as strings):
File my_imports.py:
import os, shutil
__all__ = ['os', 'shutil']
File your_other_file.py:
from my_imports import *
print(os.curdir)
Although you might want to be explicit in your other files:
File your_other_file.py:
from my_imports import os # or whichever you actually need.
print(os.curdir)
Still, this saves you having to specify the various sources each time — and can be done with a one-liner.
Alright, here is my tweak,
Create a gemfile under the package dir, like this
import numpy as np
from matplotlib import pyplot as plt
import matplotlib as mpl
Then, for other files, like app_helper.py
from .gemfile import *
This comes from here Can I use __init__.py to define global variables?

Python: Write function in module to import packages

I am trying to write a function, which is itself loaded, to quickly import a bunch of modules globally.
I thought that, essentially, loaded modules could be treated as variables so I tried:
def loadMods():
global np
import numpy as np
and when I loaded numpy (calling np) there was no problem.
What I then did was to create a separate .py file called loadTest containing
# loadTest module
# coding: utf-8
def loadMod():
global np
import numpy as np
Then attempted to import numpy using this .py file in python (2.7):
import loadTest
loadTest.loadMod()
but now when attempting calling np I get
File "<stdin>", line 1, in <module>
NameError: name 'np' is not defined
Why does this occur? Any help or alternative ways of doing this would be much appreciated. Thanks a bunch :)
Instead of making a function to do this, why not make another module? You could name it something like modules.py and put all of your imports in there:
import numpy as np
import os
import sys
...
Then, all you need to do is a wildcard import:
from modules import *
and everything will be made available.
You must first define np like that.
In loadTest:
np=None
In somewhere other
import loadTest
loadTest.loadMod()
np=loadTest.np

Categories