I have a file utils.py containing a function called f1().
From another Python script I can import utils or execfile('utils.py') and have access to f1(). What are the differences between the two methods?
There are many differences, but from your point of view the most significant is probably that import gives you more control over the namespace in which the objects defined in utils.py end up.
Let's consider three variants on import. The first is the one you asked about:
import utils
utils.f1()
utils is the only symbol that has been added to your workspace—any pre-existing f1 in your base workspace will not have been overwritten, and if there is none, then f1() on its own will not be recognized. For code I intend to maintain, I greatly prefer this way of importing, because it makes it easy for me to search my source file for all the places in which it depends on utils.
But if saying utils.f1() every time is too verbose then you can do this:
from utils import f1
f1()
Now if you say f1() that will call utils.f1(), because that is the code object that you have now associated with the name f1 in your workspace. It's now slightly harder to get an overview of where your code is reliant on the utils module. But at least this type of import statement gives you precise control over which symbols were imported and which not. You can even rename symbols during this process:
from utils import f1 as EffOne
EffOne()
Finally you can choose to lose control over the namespace entirely:
from utils import *
Now, who knows what symbols have been imported: basically everything that utils has to offer the world (or, if the utils developer took the trouble to specify an __all__ attribute, then everything listed there). I'd advise you to use import * only for quick-and-dirty programming, if at all.
This is actually the importing style that is closest to execfile from the namespace point of view: execfile('utils.py') does much the same as from utils import * in that it dumps all symbols defined by utils willy-nilly into your workspace. One slight difference is that execfile won't even limit itself to the symbols in __all__ if that is defined—in fact, the __all__ symbol itself will just get dumped in your lap along with everything else.
Beyond namespaces, there are still plenty of differences between from utils import * and execfile('utils.py'). One is caching: a second import call on utils will be very fast (the code will not be re-run), but a second call to execfile('utils.py') may take just as long as the first because the code will be re-run. Also, there may be some code (often test code) inside utils.py that the utils author does not want to run at import time, but only when the file is executed via execfile. Such code is placed inside an if __name__ == '__main__': clause.
Related
I'm writing unit test in remix-ide and I want to call functions from different addresses within a single test.
The remix-tests Github page says that you can use import "remix_accounts.sol";, but I get URL not parseable: remix_accounts.sol. How to fix that? Or maybe there's another way to call from various addresses?
Import files with relative paths, in your case, modify the following
import "remix_accounts.sol";
to
import "./remix_accounts.sol";
Also, notice that remix doesn't allow import from an ancestor directory, for example:
import "../remix_accounts.sol";
I have been trying to understand how to properly call a function from inside a subpackage in python. I wanted to be able to call the function the way I call, for example, function isfile from os package, with os.path.isfile(). I made a test package with a structure like this:
sandbox/
-- __init__.py
-- acid.py
-- pack1/
-- __init__.py
-- fly/
-- __init__.py
-- plane.py
-- by/
-- pack2/
There are only two modules there, acid.py and plane.py. Both of them contain just a function, e.g. plane.py is
"""plane module"""
def plane(x):
x=x+4
return x
To use the function in my test.py code, I put
import pack1
in sandbox/__init__.py
import fly
in sandbox/pack1/__init__.py, and
from plane import plane
in sandbox/pack1/fly/__init__.py
The test code was then:
import sandbox
print sandbox.pack1.fly.plane(3)
Is this the right way to import a function from a subpackage, or I'm misunderstanding things?
What you did certainly works, although there are several worthwhile changes to make.
First, a note about importing from packages: importing a module is semantically distinct from accessing something in a module, even though from xml import sax and from datetime import date are syntactically equivalent. It's impossible to import only part of a module, so that
import datetime
datetime.date.today() # OK: date is a class
is guaranteed to work. However, it is possible to import a package but not the modules it contains. This is a good thing for efficiency, but it does mean that
import xml
xml.sax.parse(...) # AttributeError: 'module' object has no attribute 'sax'
is an error. Unfortunately, such errors often go uncaught because some other code has already imported sax, making it available to any other code that imports xml. (The word "from" in from xml import sax is referring to the complete package on disk, not the module object xml — on which it stores the new module as an attribute!)
As an aside, note that your example of os.path is an abberation: writing
import os
os.path.isfile(...)
works, but only because os.path is not actually a module but an alias for one of posixpath, ntpath, etc. (It then gets installed in sys.modules to allow import os.path as if it were a normal module.)
As such, for a package there is a set of public modules that the user must be aware of (because they must be imported by name to be available); the rest are internal modules that the package loads itself when necessary. If a package contains no public modules, it is irrelevant to the user that it is a package (for example, importlib with its one public function is actually implemented as a package for forward compatibility with Python 3).
Now for the suggestions:
Implicit relative imports are deprecated: write from . import pack1 instead of just import pack1 in sandbox/__init__.py, for instance.
The from plane import plane (or from .plane import plane, following the above point) is problematic because it overwrites the reference to the module plane.py with a reference to the function. Instead:
Define the user-visible entry points (like plane()) directly in their package's __init__.py, importing internal functions from private modules as needed, or
Rename the module (to plane_module.py or so) to avoid the collision.
However, it's not generally a good idea to have a package automatically import its public modules anyway: it forces the client to pay for loading unused parts of the package, and it blurs the distinction between public modules and simple nested names. Instead, write client code like
import sandbox.pack1.fly
print sandbox.pack1.fly.plane(3) # the same line you had
or
from sandbox.pack1 import fly
print fly.plane(3)
if you want to avoid repeating sandbox.pack1.
It is often suggested that __init__.py be entirely empty, and in Python 3.3 it became possible to define packages without any __init__.py at all (which by necessity "makes it empty"). This policy does more than the "no automatic import" suggestion in that it precludes loading things from private modules (like plane).
There are sometimes good reasons to have a non-empty __init__.py; for example, it allows reorganzing an existing module into a package without breaking its clients. I personally see no reason to especially restrict its contents; for further discussion see What is __init__.py for?.
The init.py file makes a folder as a package so that you can import it to python prompt. If you just want to call the function "plane" from your file plane.py, add the absolute path of plane.py file to your PYTHONPATH and call the funtion as shown below.
>>> import sys
>>> sys.path.append("D:\\sandbox\\pack1\\fly")
>>> import plane
>>> print plane.__doc__
plane module
>>> print plane.plane(3)
7
If you want all the packages under "sandbox" folder to be used in your script just add the absolute path of "sandbox" folder to your PYTHONPATH and call the funtion as shown below.
>>> import sys
>>> sys.path.append("D:\\")
>>> from sandbox.pack1.fly import plane
>>> print plane.plane(3)
7
You can also import the "plane.py" module and call the function "plane" as shown below:
>>> import sys
>>> sys.path.append("D:\\")
>>> import sandbox.pack1.fly.plane
>>> print sandbox.pack1.fly.plane.plane(3)
7
I have a python structure like this:
mymodule/
globalconfig.py # variables to set environment, etc
work.py # has: from mymodule.globalconfig import *
__init__.py
tests/
testspart1/
test_work.py # has: from mymodule.work import *
From inside work.py, all is well and I can access my global config variables and functions.
From inside test_work.py, I cannot access those variables, even if I add a second import,
from mymodule.globalconfig import *
Why is this? I wanted to use the same syntax as used in my modules.
thank you!
I am using py2.7 and, to get nice rspec-style outputs and verbose diffs,
pytest --spec -vv
Ref;
1.This answer reminded me I could use another format of import. If there are no other answers I will post my workaround. how to share a variable across modules for all tests in py.test
The import syntax that worked for me was directly importing the nested python file in addition to importing the file under test.
from mymodule.work import *
import mymodule.globalconfig as myconfigs
I assume it's a name clash or import circularity issue, but I could not figure out what the problem was. It took me a while so I wanted to be sure to post the solution for future me and others.
I have written two modules m1.py and m2.py each of which uses various modules from the standard library.
For example
#m1.py
import sys
#.
#.
and
#m2.py
import os
#.
#.
What "bothers" me is that when I import in main.py the two modules m1.py and m2.py
I can use the functions defined in sys and os like this:
#main.py
print m1.sys.version
print m2.os.listdir()
Is this normal, or there is something I should consider when importing modules in my code?
Usually you don't need to worry about what is accessible in your namespace. Anyone who messes around with stuff that's not part of the module's documented API deserves whatever trouble they get. Python assumes that it's programmers are responsible adults.
The exception is when you specifically want to allow other code to use the otherwise discouraged from mymodule import * syntax. Then you want to limit what is public, so that you don't clutter up your importer's namespaces with your own internal stuff.
Here's how you can do that:
Names that begin with an underscore (e.g. _foo) are assumed to be private, and won't be imported with from mymodule import *. This isn't "real" privacy, as anyone who does a normal import will still be able to access them via mymodule._foo (but they probably shouldn't!).
If you want to make the modules you're importing private, use an as clause to give them a "private" name as described above. That is, use import os as _os.
Or, rather than messing around with underscores, you can create an __all__ variable that explicitly lists the module's public names. Only the names in the list will be imported with a from mymodule import * statement. Note that an __all__ sequence is required in packages if you want the submodules to be importable via from mypackage import *. That's because Python can't trust the filesystem not to mess with the capitalization of the filenames the package contains.
I'm reading Two Scoops Django Best Practices to make my coding style improve. I'm in relative imports and here is the sample code to make it reusable.
Old Way:
from cones.foo import bar
New way:
from .foo import bar
The code above is for cones app, what if I call the other model in other app? Do I have to put like this:
from .foo import bar
from .other import sample
OR
from .foo import bar
from test.other import sample
What is the correct way?
I usually use imports like this only for one reason
from .foo import bar
from .other import sample
The reason being
If Tomorrow, my module name changes from say 'test' to 'mytest' then the code does not require a refactoring. The code works without breaking.
Update
All imports starting with a '.' dot, only works within that package.
Cross package imports need require the whole path.
If test is another app,
from .other import sample
wont work.
Update:
You can only use relative imports when you're importing from the same app.
Inside test app
from .other import sample
will work. But you'll still need the complete form
from cones.foo import bar
if you import method defined in foo from test app.
So answering your question the second way is the correct way.