How really 'import' works in Python? - python

I can't wrap my head around how 'import' statement works in Python.
It is said to search for the packages in directories returned by sys.path(). However, even if sys module is available automatically in every Python program it's not imported automatically. So does import statement import sys module under the hood?

There are two phases which you are getting a little confused.
Python has to find the actual file (containing code) that you want to import, parse it, execute it, and store it somewhere.
It then has to bind the name of the imported module locally to the module object.
That is, the process "find the module sys and turn it into a module object" is not the same as "define the variable sys to mean the module".
You can check which modules have been loaded by looking in sys.modules.
As a separate issue, there are a few basics of Python that are actually hardcoded into the interpreter, not represented as separate files on disk. sys is one of these modules: there is no sys.py file; instead, it's compiled C code that's included in the python.exe binary.

sys module vs import statement - aka. "chicken or the egg?"
I believe sys module documentation says it all:
This module provides access to some variables used or maintained by the interpreter and to functions that interact strongly with the interpreter. It is always available.
So, to put it shortly and in different words: interpreter has some variables that you can access by using sys module - sys.path is one of such variables.
Question no. 2. - How import works
When it comes to "how import statement works", you can read about it here: http://docs.python.org/2/reference/simple_stmts.html#import. However, it is not really related to the main part of your question: the relation of import statement and importing sys module.

Related

How to import packages from inside another package

So, I am making an application in python where i am inside a package, and i want to a import a package from outside that older. I have tried os.chdir() but that doesn't work. I have tried to import it by simply saying
I expect the package to be imported and any file that i want can be used as many times as possible so that i can have a more structed program, and easier to understand
My username is too new to comment so I'll indirectly answer, if your UserData is a module (given there is an __init__), and so too is SignLoginLogic, and they are at the same directory level, I have never seen a case where you're importing using your requested method (importing somehow from another module's __init__.py directly). See https://docs.python.org/3/reference/import.html. You should be importing SignLoginLogic into your module using something like from SignLoginLogic import WhatYouWantFromIt or otherwise a relative import.

In python, even though I imported no modules, how I'm able to use functions like sort, append, insert, etc?

I have just started learning Python. I was just testing different features of python on python's console in Terminal (Ubuntu's terminal).
Even though I didn't imported any modules, how can I could still use functions like append(), insert(), print(), etc.
I used to program in C language, where I must include 'stdio.h' header file just to 'print' a string. So I was expecting same behaviour in Python.
Is there any standard Module which is by default imported in every Python program's 'interpretation'?
You could check the modules that are loaded in a python file by running
import sys
sys.module.keys()
Functions like print are part of the __builtin__ module that is loaded by default.

Python: how to ensure your code won't be accidentally imported by the libraries you use?

A few hours ago I was careless enough to name my short script as code.py. Apparently, there is such a package which is used e.g. by ptvsd or pdb. This led to my code.py to be imported instead and caused a bunch of nested unhandled exceptions with missing imports upon trying to debug my code. What was making it more frustrating is that traceback didn't show any sign of importing my code.py file, so I spent quite a while to find the source of the problem.
I'd like to avoid such situations in the future, so my question is: what's the best practice to ensure that the modules you use aren't importing your code by mistake due to such a name collision?
This is a common gotcha, and actually there's no failsafe way to avoid it. At least you can make sure your modules all live in packages (at least one package if that's a small project with no reusable code) so that you'd use them as from mypackage import code instead of import code (also make sure you use either absolute imports etc), and that you always run your code from the directory containing the package(s), not from within the package directory itself (python inserts the current working directory in first position of sys.path).
This won't prevent ALL possible name masking issues but it should minimize them. Now from experience, once you've experienced this kind of issues at least once, you usually spot the symptoms very quickly - the most common and quite obvious being that some totally unrelated stlib or third-part module starts crashing with ImportErrors or AttributeErrors (with "module X has no attribute Y" messages). At this point, if you just added a new module to your own code, chances are it's the new module that breaks everything, so you can just rename it (make sure you clean up .pyo/.pyc files if any) and see if it solves the issue. Else check the traceback to find out which imports fails, most of the time you'll find you have a module or package by the same name in your current working directory.
You can't avoid completely, that somebody is able to import your module by mistake.
You can structure your code better in subpackages going from "well known" to "less known" names. E.g. if you are developing code for a certain company then you might want to structure like:
company.country.location.department.function
If your code is then getting more accepted and used by others, you can bring the code in the upper namespace, so that it is made available in company.country.location.department.function
and company.country.location.department
You can modify sys.path at the beginning of your main module, before you start importing other modules:
import sys
sys.path.append(sys.path.pop(0))
so that the main module's starting directory is placed at the last of the module search paths rather than at the front, in order for other modules of the same name to take precedence.
EDIT: To all the downvoters, this answer actually works.
For example, running code.py with the following content:
import pdb
pdb.run('print("Hello world")')
would raise:
AttributeError: module 'pdb' has no attribute 'run'
because code.py has no run defined, while running code.py with the following content instead:
import sys
sys.path.append(sys.path.pop(0))
import pdb
pdb.run('print("Hello world")')
would execute pdb.run properly:
> <string>(1)<module>()
(Pdb)

Importing user defined modules in python from a directory

I'm trying to import a module I wrote in python that just prints out a list containing numbers. The issue I'm having is that I want to be able to import it from a separate directory but the answers I have read so far don't seem to be working for my situation.
For example, given I want to import printnumbers.py from a directory in my documents folder I am supposed to implement the following:
import sys
sys.path.append('/home/jake/Documents')
import printnumbers.py
This snipit of code results in a "Import error" telling me that the specified module does not exist. I'm not exactly sure where to proceed from here, I have checked multiple times to make sure it's the right spelling for the path as well as for the module name. I'm still trying to understand exactly what appending to the "sys.path" does. From what I understand it's telling the program to search for modules in that directory?
Thanks for anyone who answers my rather novice question. I'm just looking for a better understanding of it that the python documentation isn't providing for my frame of mind.
When the file is printnumbers.py, the module is called printnumbers (without the .py). Therefore use
import printnumbers
import sys
sys.path.append('/home/jake/Documents')
appends '/home/jake/Documents' to the end of sys.path. The directories listed in sys.path are searched (in the order listed) whenever an import statement causes Python to search for a module. (Already imported modules are cached in sys.modules, so Python does not always need to search sys.path directories to import a module...)
So if you have a file /home/jake/Documents/printnumbers.py, then import printnumbers will cause Python to import it provided there is no other file named printnumbers.py in a directory listed in sys.path ahead of /home/jake/Documents/.
Note that injecting directories into sys.path is not the usual way to set up Python to search for modules. Usually it is preferable to add /home/jake/Documents to your PYTHONPATH environment variable. sys.path will automatically include the directories listed in the PYTHONPATH environment variable.
and one more thing, use an empty __ init __.py file in you directory
to make it as a python package (only then Python will know that this
directory is a Python package directory other than an ordinary
directory). Thus you can import modules from that package from
different directory.

Where should sys.path.append('...') statement go?

Just after standard pythonmodule imports?
If I postpone it to the main function and do my specific module imports before it, it gives error (which is quite obvious). Python Style guide no where mentions the correct location for it.
It should go before the import or from statements that need it (which as you say is obvious). So for example a module could start with:
import sys
import os
import math
try:
import foo
except ImportError:
if 'foopath' in sys.path: raise
sys.path.append('foopath')
import foo
Note that I've made the append conditional (on the import failing and the specific module's path not being on sys.path yet) to avoid the risk of sys.path ending up with dozens of occurrences of string foopath, which would not be particularly helpful;-).
One reason this isn't mentioned in PEP 8 or other good Python style guides is that modifying sys.path isn't something you want to do in a real program; it makes your program less robust and portable. A better solution might be to put your package somewhere that would already be in sys.path or to define PYTHONPATH systemwide to include your package.
I often use a shell script to launch my python applications: I put my sys.path.insert (append) statement just after the "standard" python module imports in my "launch python script".
Using sys.path.insert(0, ...) gets your "imports" in priority in the path list.
I generally do it before importing anything. If you're worried that your module names might conflict with the Python stdlib names, then change your module names!
I think it's a matter of taste. But most people tend to put it behind the import sys :-)
I prefer wrapping it in an extra function:
def importmod_abs(name):
sys.path.append() ..
__import__ ...
sys.path.pop()
... this way sys.path remains clean. Of course that's only applicable to certain module structures. Anyways, I'd import everything that works without altering sys.path first.

Categories

Resources