Background: I have a few tight loops in a Python program that are called repeatedly, which include the datetime.datetime.now() method, as well as the datetime.datetime.min and datetime.datetime.max attributes. For optimization, I would like to import them into the local namespace, avoiding the repeated, unnecessary module hierarchy name look-up, like so:
from datetime.datetime import now, min, max
However, Python complains:
Traceback (most recent call last):
File "my_code.py", line 1, in <module>
from datetime.datetime import now, min, max
ImportError: No module named datetime
Question: Why doesn't the above submodule import work?
Workaround: I can instead do this:
import datetime
dt_now = datetime.datetime.now
dt_min = datetime.datetime.min
dt_max = datetime.datetime.max
But, I'm curious why the more traditional approach does not work? Why can I not import methods and properties directly from the datetime.dateime submodule? ... And, is there any reason to avoid the above workaround (besides readability, outsmarting myself, etc.)?
Thanks!
datetime.datetime is not a submodule. datetime is a class within the datetime module. now is a method of that class. You can't use from...import... to import individual methods of a class. You can only use it to import individual modules from a package, or individual objects that exist at the top level of a module.
As for your workaround, if you want shorthand, I find it more readable to do this:
from datetime import datetime as dt
dt.now()
# you can also use dt.max, dt.min, etc.
If you really want to put those methods directly in local variables, then your workaround makes sense.
Related
I'm literally days-new to Python programming after years of C++ and C programming, and am trying to get a feel for the grammar.
In the following very-beginner code:
from datetime import datetime
from datetime import date
print( datetime.now() )
# print( now() ) # NameError: name 'now' is not defined
print( date(2005, 2, 27) )
# print( datetime.date(2005, 2, 27) ) # TypeError: descriptor 'date' requires a 'datetime.datetime' object but received a 'int'
...why is it necessary to scope now() in datetime but apparently incorrect to do so with date(...)?
The learning material I'm referencing said the two import statements mean I'm "importing the date and datetime classes from the datetime standard module." Possibly biased from my C++ background, I'm equating module with namespace and would have thought this meant (1) you'd need to explicitly scope functions and classes with the module they came from (like std::sort()), or (2) not need explicit scoping because the from/import clause is akin to CC++'s using clause. So the grammar of the above looks odd to me because it looks like I'm using two "things" that come from the datetime "namespace," and I must scope one thing but not the other.
FWIW, I use vim as my editor - I wonder: would something about this have been more transparent with a a graphical/autosuggest-enabled editor?
To any answerers, I'd be grateful if you could explain how an experienced Python programmer would go about finding out the answer to a question like this. What I mean is: in C/C++, I'd look up whatever .h I #include to find out what's what - how do you go about "looking up" the datetime "module"?
You're correct - you don't need to scope! This is a slightly confusing situation because the datetime module has a class which is also called datetime.
So what's happening in each of these:
print(datetime.now()) # Call the now() class method of the datetime class and print its output
print(now()) # now() is not defined in the namespace, hence the error
print(date(2005, 2, 27)) # Instantiate a date object and print its representation
print(datetime.date(2005, 2, 27)) # This is trying to call the date() method of the datetime class, which doesn't exist, hence the error.
With the last case, if you had just done import datetime, the whole datetime module would have been imported. In that case, you can instantiate a date class object by doing datetime.date(2005, 2, 27).
Hope that makes a tiny bit of sense!
The importing in python ist simple. When you import
from datetime import datetime
then you have from modul datetime only import the class / function datetime. (In this case a class). Your interpreter don't know the function "now" but you can access to it when you take the loop over that what you imported.
datetime.now()
after your second import
from datetime import date
your compiler knows the classes date and datetime. When you try
print( datetime.date(2005, 2, 27) )
then it is not that what you expect. You try to call from class datetime the function date which have other parameters as the class date from modul datetime.
The problem with the modul datetime is that it contains a class with datetime so it is a little bit confusing.
In first.py, I imported the datetime library and called a method which is written in second.py. The method works well without importing the datetime libirary in second.py.
first.py
from datetime import datetime
import second
def method1(time):
return datetime.strptime(time,"%Y/%m/%d")
a = method1("2019/08/01")
b = second.method2(a)
second.py
def method2(para1):
return para1.second
Output
0
Should second.py import datetime so that para1.second can work? Can someone help explain the rationale behind?
You only need to import modules explicitly when you need to use their names. In first.py, for example, you're using things in the datetime module directly, and referring to it by name. So, you do import datetime, and then call datetime.strptime() on that module you imported.
In second.py, however, you don't have to do import datetime. This is because of how python handles attributes - when you do para1.second, python doesn't need to know exactly what type of variable para1 is - it just checks to see whether it has a field called second. And it does, so it returns that. Nowhere in second.py are you referring to datetime directly - only indirectly, via a variable that was defined from it.
Also consider that the datetime module does a lot of stuff on its own, and almost certainly imports other dependencies that you're not aware of and you're not importing yourself. But you can still use the datetime module, because you don't need to explicitly refer to those modules it's using behind the scenes. They're still in memory somewhere, and if you call certain methods from datetime, that code will still get executed, but you don't need to be directly aware of it.
Python usually uses duck typing1. This means that instead of requiring a particular type for an object, it looks at the actual attributes it has.
What this means in your case is that method2 does not care in the slightest whether you pass in a datetime object or not. All that's required is that the input para1 have a second attribute.
Importing datetime into second.py would be counter-productive. It wouldn't affect the operation of your method in any way, but it would polute your namespace and set up an implication that isn't necessarily true.
1 A notable counterexample is a sum of strings, e.g. sum(['a', 'b'], ''). Aside from that, your own code can choose what to do as you see fit if course.
I'm having some confusion on some of my code which was previously working (yesterday). Using python 2.7.6
I had
from datetime import datetime
openfor = (datetime.strptime(row[1],"%Y-%m-%d %H:%M:%S") - datetime.strptime(row[2], "%Y-%m-%d %H:%M:%S")).total_seconds()
and it returned the value that is required. As of this morning it is generating
AttributeError: 'module' object has no attribute 'strptime'
If I use the below, with or without the import it works.
openfor = (datetime.datetime.strptime(row[1],"%Y-%m-%d %H:%M:%S") - datetime.datetime.strptime(row[2], "%Y-%m-%d %H:%M:%S")).total_seconds()
It is no real big deal, because it works, but the code looks ugly and my curiosity is piqued.
So any suggestions on why this would stop working? And how to resolve?
Thanks
Per the comments, the import statement
from pylab import *
is the cause of the problem. This imports pylab and copies all the names in the pylab namespace into the global namespace of the current module. datetime is one of those names:
In [188]: import pylab
In [189]: 'datetime' in dir(pylab)
Out[189]: True
So datetime is getting reassigned to the module rather than the class.
Somewhere between
from datetime import datetime
and
openfor = (datetime.strptime(row[1],"%Y-%m-%d %H:%M:%S") - datetime.strptime(row[2], "%Y-%m-%d %H:%M:%S")).total_seconds()
datetime is getting redefined to equal the module datetime rather than the class datetime.datetime.
The cause of this problem is in code that you have not posted.
(But an import statement, import datetime, is likely the culprit. Also be careful not to use from module import *, as this could pollute the calling module's namespace with names from the other module. This could include datetime.)
By the way, some experts recommend never using
from module import function
and instead always importing modules only:
import module # or
import module as foo
While this may be a stylistic choice, adhering to this rule makes it extremely clear where everything is coming from.
I want to be able to access the strptime function directly (no datetime.datetime.strptime() or datetime.strptime().)
I can do this:
from datetime import datetime
strptime = datetime.strptime
But is there a way to accomplish the same thing on the import line?
Also, can you do multiple items on one line?
Here's pseudocode of what I really want to do:
from datetime.datetime import strftime, strptime
Datetime is just the example case, a similar thing would be useful for importing class methods in other libraries.
Those are methods of the datetime type and can't be imported directly. You can't directly import anything below the top-level namespace of a module. From the documentation:
The from form does not bind the module name: it goes through the list of identifiers, looks each one of them up in the module found in step (1) [i.e., the module being imported], and binds the name in the local namespace to the object thus found.
That is, the imported names must be names in the module namespace. They can't be any more deeply nested than that. So you can't, as you apparently want to do, import just certain methods of classes in the module.
The answer to the question "Can I do this on the import line?" is no.
See the definition of the import statement in Python 2. The statement imports things from modules. There is a datetime class inside the datetime module. The best you can do is
from datetime import datetime
You already understand well what this does, as you used it perfectly in your question. It looks like you wanted to do
from datetime import datetime.strptime
but that is a syntax error because datetime.strptime is not an indentifier.
You can't say
from datetime.datetime import strptime
either because Python would look for a module named datetime.datetime.
The import statement just doesn't work the way you want it to.
Note that the author of the datetime module chose to make strptime a classmethod (using #classmethod) rather than a function. So if you want to use strptime without the class qualifier you will have to do what you did, namely assign to a variable named strptime.
I need some clarification on how module and class level imports are handled when coexisting in the same namespace. See the following examples:
Works:
import datetime
print datetime.datetime.utcnow()
Fails:
from datetime import datetime
print datetime.datetime.utcnow()
Error: AttributeError: type object 'datetime.datetime' has no
attribute 'datetime'
Works:
from datetime import datetime # Is this ignored?
import datetime
print datetime.datetime.utcnow()
What exactly is happening in the 3rd example? Is the second module import replacing the class-specific first import? Does this mean that module and class level imports shouldn't be mixed in the same namespace?
There is no priority is such. The outcome is determined by the order in which import statements are executed, as follows.
If you try to import several things called X into your namespace, each import would rebind X to whatever it's importing.
Therefore at the end it will be last import that'll be in effect as far as the name X in concerned.
This is precisely what happens in your third example:
from datetime import datetime # This isn't ignored, but the name is immediately rebound
# by the next line
import datetime # Rebinds the name
Some of the IDE's that support python would give you the explanation, but yes, you're redefining (overwriting, replacing) the import in the 3rd example. Each name within a file is distinct. If you need access to a module and a class that share a name you need to use something like from datetime import datetime as dt.
An import is really just an assignment: it sets a name in your current namespace. So, in the third case, you set the name datetime as equal to the datetime class, then immediately reassign it to the datetime module.
There is no reason to do it like this:
from datetime import datetime
print datetime.datetime.utcnow()
this code, on the other hand, would do exactly what you want it to:
from datetime import datetime
print datetime.utcnow()
Your first example imports the datetime module and provides a datetime label in the local namespace representing it, then calls the utcnow() method of the datetime object belonging to the datetime module. The second adds the datetime.datetime object (not the module) to the local namespace with the label datetime, but the datetime object has no attribute datetime, so you get the exception. The third example assigns the datetime.datetime object to the label of that name in the namespace, then reassigns the label to the datetime module. So ignoring the mechanics of import that are irrelevant to this question (basically, adding modules to sys.modules if they are not there yet), what you have is equivalent to:
datetime = sys.modules['datetime']
datetime.datetime.utcnow()
then
datetime = sys.modules['datetime'].datetime
datetime.datetime.utcnow()
then
datetime = sys.modules['datetime'].datetime
datetime = sys.modules['datetime']
datetime.datetime.utcnow()