My 2.7.5 version of __future__.print_function doesn't allow use of the new argument:
>>> print('hi', end='')
Parsing error SyntaxError: invalid syntax (line 1)
I'll ask about why this is in a separate post if I can't figure that out. For now, I wanted to see what arguments were available in my environment's version of this function.
I looked at this SO post and some related ones, but these do not seem to work when I try:
>>> print.func_code.co_varnames
Parsing error SyntaxError: invalid syntax (line 1)
>>> print_function.func_code.co_varnames
Runtime error
Traceback (most recent call last):
File "<string>", line 1, in <module>
AttributeError: _Feature instance has no attribute 'func_code'
I'm guessing that the special nature of __future__ functions is why this standard technique fails.
Is there another way to check what args my version __future__.print_function takes?
You are trying to treat a built-in function (implemented in C) as a user-defined function. They are not the same thing. .func_code is only defined for user-defined functions (implemented in Python).
The __future__ module only holds metadata about features, the __future__.print_function object is not the same object as the print() function. Instead, the object tells you more about what version of Python first supported the feature, and in what version the feature becomes mandatory (and the from __future__ import becomes a no-op), as well as a bitfield flag for the compile() function:
>>> import __future__
>>> __future__.print_function
_Feature((2, 6, 0, 'alpha', 2), (3, 0, 0, 'alpha', 0), 65536)
>>> __future__.print_function.optional
(2, 6, 0, 'alpha', 2)
>>> __future__.print_function.mandatory
(3, 0, 0, 'alpha', 0)
>>> __future__.print_function.compiler_flag
65536
In Python 2.7, built-in function objects such as print() simply do not have enough information for you to discover what arguments they support. In Python 3, this is slowly changing as more and more built-in types are given metadata, but the print() function is not yet among them:
>>> import inspect
>>> inspect.signature(print)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/mpietre/Development/Library/buildout.python/parts/opt/lib/python3.4/inspect.py", line 2045, in signature
return _signature_internal(obj)
File "/Users/mpietre/Development/Library/buildout.python/parts/opt/lib/python3.4/inspect.py", line 1947, in _signature_internal
skip_bound_arg=skip_bound_arg)
File "/Users/mpietre/Development/Library/buildout.python/parts/opt/lib/python3.4/inspect.py", line 1884, in _signature_from_builtin
raise ValueError("no signature found for builtin {!r}".format(func))
ValueError: no signature found for builtin <built-in function print>
I'm not sure where you got the idea from that new is a valid keyword for print() in any Python version however. No version of Python exists that supports that argument.
The only argument that is missing from print() in Python 2 and present in Python 3.3 and up, is the flush argument, see the Python 3 docs for print():
[...] if the flush keyword argument is true, the stream is forcibly flushed.
Changed in version 3.3: Added the flush keyword argument.
The only way to test for that (other than testing with sys.version_info >= (3, 3)) is to try and use it:
from io import StringIO
try:
print('', end='', flush=False, file=StringIO())
print_supports_flush = True
except TypeError:
print_supports_flush = False
Related
Just trying to mess around and learn about python ctypes according to the official documentation at https://docs.python.org/3.8/library/ctypes.html
Everything works just fine until:
ValueError is raised when you call an stdcall function with the cdecl calling convention, or vice versa:
>>> cdll.kernel32.GetModuleHandleA(None)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: Procedure probably called with not enough arguments (4 bytes missing)
>>>
>>> windll.msvcrt.printf(b"spam")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: Procedure probably called with too many arguments (4 bytes in excess)
>>>
quoted from official documentaion, while i get is:
>>> cdll.kernel32.GetModuleHandleA(None)
1374486528
>>> windll.msvcrt.printf(b"spam")
4
according to those MS documentation, seems these function calls work just fine
What's more, I also tried to mess around with the argument number so as to raise a ValueError, but that's what I get:
>>> cdll.kernel32.GetModuleHandleA(None,0,0)
1374486528
>>> windll.kernel32.GetModuleHandleA(0,0,0)
1374486528
>>> windll.kernel32.GetModuleHandleA()
0
>>> cdll.kernel32.GetModuleHandleA()
0
Seems the last two function calls does return null as there was an error, but no Value error exception.
The only error i got is OSError, just as the documentation example shows.
Can anyone explain this? I create virtual environment using conda and I test these codes both in python 3.6.12 and python 3.8.5.
And by the way ,according to the documentation: "ValueError is raised when you call an stdcall function with the cdecl calling convention, or vice versa", I wonder what exactly "call an stdcall function with cdecl calling convention" means? Maybe just by giving different number of arguments rather than the function required?
__stdcall and _cdecl have no difference on 64-bit compilers. There is only one calling convention and the notations are ignored and both WinDLL and CDLL work. 32-bit code is where it matters and the correct one must be used.
You should still use the appropriate WinDLL or CDLL in scripts if you want the script to work correctly on both 32-bit and 64-bit Python.
A simple snippet in Python 3.6.1:
import datetime
j = iter(datetime.datetime.now, None)
next(j)
returns:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
instead of printing out the classic now() behavior with each next().
I've seen similar code working in Python 3.3, am I missing something or has something changed in version 3.6.1?
This is definitely a bug introduced in Python 3.6.0b1. The iter() implementation recently switched to using _PyObject_FastCall() (an optimisation, see issue 27128), and it must be this call that is breaking this.
The same issue arrises with other C classmethod methods backed by Argument Clinic parsing:
>>> from asyncio import Task
>>> Task.all_tasks()
set()
>>> next(iter(Task.all_tasks, None))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
If you need a work-around, wrap the callable in a functools.partial() object:
from functools import partial
j = iter(partial(datetime.datetime.now), None)
I filed issue 30524 -- iter(classmethod, sentinel) broken for Argument Clinic class methods? with the Python project. The fix for this has landed and is part of 3.6.2rc1.
I assume you're using CPython and not another Python implementation. And I can reproduce the issue with CPython 3.6.1 (I don't have PyPy, Jython, IronPython, ... so I can't check these).
The offender in this case is the replacement of PyObject_Call with _PyObject_CallNoArg in the C equivalent of the callable_iterator.__next__ (your object is a callable_iterator) method.
The PyObject_Call does return a new datetime.datetime instance while _PyObject_CallNoArg returns NULL (which is roughly equivalent to an exception in Python).
Digging a bit through the CPython source code:
The _PyObject_CallNoArg is just a macro for _PyObject_FastCall which in turn is a macro for _PyObject_FastCallDict.
This _PyObject_FastCallDict function checks the type of the function (C-function or Python function or something else) and delegates to _PyCFunction_FastCallDict in this case because datetime.now is a C function.
Since datetime.datetime.now has the METH_FASTCALL flag it ends up in the fourth case but there _PyStack_UnpackDict returns NULL and the function is never even called.
I'll stop there and let the Python devs figure out what's wrong in there. #Martijn Pieters already filed a Bug report and they will fix it (I just hope they fix it soonish).
So it's a Bug they introduced in 3.6 and until it's fixed you need to make sure the method isn't a CFunction with the METH_FASTCALL flag. As workaround you can wrap it. Apart from the possibilities #Martijn Pieters mentioned there is also a simple:
def now():
return datetime.datetime.now()
j = iter(now, None)
next(j) # datetime.datetime(2017, 5, 31, 14, 23, 1, 95999)
print.__doc__ outputs:
SyntaxError: invalid syntax
where as
>>> getattr(__builtin__,"print").__doc__
Outputs:
print(value, ..., sep=' ', end='\n', file=sys.stdout)
Prints the values to a stream, or to sys.stdout by default. Optional keyword arguments:
file : a file-like object (stream); defaults to the current sys.stdout.
sep: string inserted between values, default a space.
end: string appended after the last value, default a newline.
Can anyone help me understand why print.__doc__ is giving a syntax error instead of printing the doc string
In Python 2 (or Python < 2.6 to be very exact) print is absolutely nothing like a function, and thus does not have docstring. It doesn't even evaluate all of its arguments before it starts printing:
>>> print 42, a
42
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
42 was printed before the a was evaluated. print is a statement that expects 0 to N comma separated expression following it, optionally preceded by the construct >> file, the construct print.__doc__ is illegal. It makes as little sense as if.__doc__, or return.__doc__.
However starting with Python 2.6, the print function is available in the __builtin__ module, but is not used by default as the print statement collides with it, unless the parsing for print the statement is disabled by from __future__ import print_function.
Print isn't globally available as a function in Python 2, so you can't treat it as an object. It's a statement.
In Python 3, or Python 2 with from __future__ import print_function, however, print is a normal function and you can read the __doc__ attribute.
See: https://docs.python.org/2/library/functions.html#print
Note: This function is not normally available as a built-in since the name print is recognized as the print statement. To disable the statement and use the print() function, use this future statement at the top of your module:
from __future__ import print_function
I'm having problems supporting python2 and python3 on a type() call. This demonstrates the problem:
from __future__ import unicode_literals
name='FooClass'
type(name, (dict,), {})
No problem on python3, but on python2:
Traceback (most recent call last):
File "test.py", line 6, in <module>
type(name, (dict,), {})
TypeError: type() argument 1 must be string, not unicode
This is related to Any gotchas using unicode_literals in Python 2.6?. In that question, someone recommends typecasting to a bytestring, so naively I thought about using six.b():
A “fake” bytes literal. data should always be a normal string literal.
In Python 2, b() returns a 8-bit string. In Python 3, data is encoded
with the latin-1 encoding to bytes.
So it looks like this:
from __future__ import unicode_literals
import six
name='FooClass'
type(six.b(name), (dict,), {})
But it fails on both python2 and python3:
$ python2 test.py
Traceback (most recent call last):
File "test.py", line 6, in <module>
type(six.b(name), (dict,), {})
TypeError: type() argument 1 must be string, not unicode
$ python3 test.py
Traceback (most recent call last):
File "test.py", line 6, in <module>
type(six.b(name), (dict,), {})
TypeError: type() argument 1 must be str, not bytes
So it seems that really, type() wants a python2 str which is a python3 bytestring on python2, but it wants a python3 str which is a python2 unicode string on python3.
What do you think ?
Is there something I don't understand ?
Or is there a real incompatibility with type() on python 2 and 3 ?
Isn't there any way to have the same type() call supporting both 2 and 3 ?
Shouldn't a tool like six provide a wrapper around type() in that case ?
six.b is written under the assumption that you won't use unicode_literals (and that you'll pass a string literal to it, as the documentation states), so the Python 2 implementation is just def b(s): return s as a Python 2 string literal is already a byte string.
Either don't use unicode_literals in this module, or use (as a comment suggests) str(name). In Python 3, that is a no-op. In Python 2, it silently converts the unicode string to a byte string (assuming some encoding that I can't be bothered to remember, but it's a superset of ASCII so you should be fine).
Apologies in advance for conflating functions and methods, I don't have time at the moment to sort out the terminology but I'm aware of the distinction (generally).
I'm trying to control what functions are run by my script via command-line arguments. After a lot of reading here and elsewhere, I'm moving in the direction of the following example.
# After connecting to a database with MySQLdb and defining a cursor...
cursor.execute(some_query_stored_earlier)
for row in cursor:
for method_name in processing_methods: # ('method1','method2', ...)
globals()[method_name](row)
(Clarification: processing_methods is a tuple of user-defined strings via command-line argument(s) with nargs='*'.)
However, I'm running into problems with print (no surprise there). I would like print to be:
among the methods that MIGHT be specified from the command line;
the default method when NO methods are specified from the command line;
not performed if ONLY OTHER methods are specified from the command line.
Let me acknowledge that I can make things easier on myself by eliminating the first and third criteria and simply doing:
for row in cursor:
print row
for method_name in processing_methods:
globals[method_name](row)
But I really don't want to ALWAYS print every row in what will sometimes be a several-million-rows result. I did a future import, hoping that would solve my problem - no such luck. So I did a little exploring:
>>> from __future__ import print_function
>>> print
<built-in function print>
>>> globals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, 'print_function': _Feature((2, 6, 0, 'alpha', 2), (3, 0, 0, 'alpha', 0), 65536), '__package__': None}
>>> a = "Hello, world!"
>>> print(a)
Hello, world!
>>> globals()['print'](a)
Traceback (most recent call last):
File "<pyshell#33>", line 1, in <module>
globals()['print'](a)
KeyError: 'print' # Okay, no problem, obviously it's...
>>> globals()['print_function'](a)
Traceback (most recent call last):
File "<pyshell#34>", line 1, in <module>
globals()['print_function'](a)
AttributeError: _Feature instance has no __call__ method # ...huh.
So then I did a little more reading, and this Q&A prompted some more exploring:
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__']
>>> __builtins__
<module '__builtin__' (built-in)>
>>> 'print' in dir(__builtins__)
True # now we're getting somewhere!
>>> __builtins__.print something
SyntaxError: invalid syntax # fair enough.
>>> __builtins__.print('something')
SyntaxError: invalid syntax # wait, what?
>>> dir(__builtins__.print)
SyntaxError: invalid syntax # -_-
Something is going on here that I just don't understand, and this other Q&A hasn't made it any clearer. I think the easy solution to my particular issue is going to be a mildly awkward wrapper like:
def printrows(row):
print row # assuming no future import, of course
But it's driving me crazy: Why can't I access print via the globals dictionary? Am I doing it wrong, or is it just something you can't do with built-in functions?
Did you forget to repeat from __future__ import print_function when you opened a new shell for your second try (where you got all those syntax errors)? It works for me: https://ideone.com/JOBAAk
If you do an otherwise seemingly useless assignment, it works the way I think you expected. I'm not an expert in the internals at work here, so I can't explain WHY this works, but it does.
>>> from __future__ import print_function
>>> row="Hello world"
>>> print = print
>>> globals()['print'](row)
Hello world