Python3: Use a variable defined within a function - function

I am confused over this behavior seen in Python3 and I was wondering if there is a way around it or if I am doing something wrong.
I have seen this in the command-line and scripts. I define a function called "SETVAR()". SETVAR() will use getpass.getuser() (which was imported) and save the output to the variable USER. The function is executed, but when USER is printed, I get an error stating the variable was not defined. If I define the variable outside of a function, all is well. However, in my scripts, I want to use variables defined and made in a function. Can it be done?
>>> def SETVAR():
... USER = getpass.getuser()
...
>>> SETVAR()
>>> print(USER)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'USER' is not defined
>>> USER = getpass.getuser()
>>> print(USER)
collier
Question: How do I use variables defined and created in functions that have been defined and executed whether in the command-line or script?

Even if you define and create the variable inside a function, you can let Python know that you want the resulting variable to be globally accessible;
>> def SETVAR():
... global USER
... USER='olle'
...
>>> SETVAR()
>>> print(USER)
olle
>>>
EDIT: I tend to agree with #Wooble in the comments that this is something you may want to think twice about using in most circumstances. For simple scripts it can be very useful, but for more complex situations it can make the code hard to follow.

Related

positional argument follow keyword argument

There are code below:
CSV_COLUMNS = ['survived', 'sex', 'age', 'n_siblings_spouses', 'parch',
'fare', 'class', 'deck', 'embark_town', 'alone']
dataset = tf.data.experimental.make_csv_dataset(..., column_names=CSV_COLUMNS, ...)
when I run this code on my tensorflow object that I was followed with google tensorflow guide book, I got a Type Error: positional argument follow keyword argument.
when I tried to debug it as following
CSV_COLUMNS = ['survived', 'sex', 'age', 'n_siblings_spouses', 'parch', 'fare', 'class', 'deck', 'embark_town', 'alone']
dataset = tf.data.experimental.make_csv_dataset(..., ..., column_names=CSV_COLUMNS)
then I got another Type Error: make_csv_dataset_v2() missing 1 required positional argument: 'batch_size'
finally, I changed it again
CSV_COLUMNS = ['survived', 'sex', 'age', 'n_siblings_spouses', 'parch', 'fare', 'class', 'deck', 'embark_town', 'alone']
dataset = tf.data.experimental.make_csv_dataset(..., column_names=CSV_COLUMNS, batch_size = 64)
another type error: 'ellipsis' object is not iterable
I am gonna crazy!
An error "SyntaxError: positional argument follows keyword argument" (I don't think that was a TypeError like you suggested) means that you're using arguments to a function call like this:
some_function(10, b=20, 30)
Note how the middle parameter is explicitly named with a keyword 'b', but the 1st and 3rd are not, they rely on being in the correct position.
Doing that, using a keyword argument before you've assigned all the positional arguments you need, is not allowed. Since Python does allow positional use of keyword arguments, there's a few ways to fix this. For example:
def some_function(a, b, c=0, d=1):
pass
# these are OK
some_function(10, 20)
some_function(10, b=20)
some_function(10, 20, 30)
some_function(10, 20, d=40)
# this is not OK
some_function(10, b=20, 30)
# this is the fix:
some_function(10, b=20, c=30)
For that same example function, if you were to call it like this:
some_function(10, c=30)
You'd get the second error you mention: "TypeError: some_function() missing 1 required positional argument". This makes sense, because what value does b now have?
The last error message "'ellipsis' object is not iterable" is far more specific. There's a special object in Python, called Ellipsis, also written as .... It is not an iterable (i.e. you can't do something like for x in ...) and the error you're getting probably means it gets assigned to some parameter which expects an iterable to be passed.
You should probably very carefully examine what arguments you are passing and to what parameters you expect those arguments to be assigned and once you fix that, this error will no longer appear either. Going into why it would be caused exactly is too much of a red herring.
It's possible you actually want or need to use the ellipsis, to tell an object or function to auto-fill some parameters and avoid passing a number of arguments, but in that case you need to be very specific about the libraries you're using, because that's not standard Python behaviour, but specific to what happens in those libraries and you should probably refer to the documentation for them.

IndexError: list index out of range

I have a data list which I got from splitting html with regex.
data_list = re.findall(r'<tr.*?>(.*?)<\/tr>', html)
When I loop in data_list I want to defining variable open for example
open = re.findall(r'kurs".*?>(.*?)<\/td', x)[0].strip('</span>')
and it gives me an error :
Traceback (most recent call last):
File "", line 2, in
open = re.findall(r'kurs".?>(.?)</td', x)[0].strip('')
IndexError: list index out of range
Thank you in advance
This error means that an element with such an index doesn't exist in the list. So there is no first element in the list re.findall returned, and this means it found nothing.
By the way, it is not recommended to use regular expressions for parsing HTML, better use HTML-oriented frameworks like BeautifulSoup and lxml.

Python backtracking

I have a basic problem in Python where I have to verify if my backtracking code found some solutions (I have to find all sublists of 1 to n numbers with property |x[i] - x[i-1]| == m). How do I check if there is some solution? I mean the potentially solutions I find, I just print them and not save them into memory. I have to print a proper message if there is no solutions.
As I suggested in comment, you might want to dissociate computing from I/O printing, by creating a generator of your solutions of |x[i] - x[i-1]| == m
Let's assume you defined a generator for yielding your solutions:
def mysolutions(...):
....
# Something with 'yield', or maybe not.
....
Here is a generator decorator that you can use to check if an implemented generator has a value
from itertools import chain
def checkGen(generator, doubt):
"""Decorator used to check that we have data in the generator."""
try:
first = next(generator)
except StopIteration:
raise RuntimeError("I had no value!")
return chain([first], generator)
Using this decorator, you can now define your previous solution with :
#checkGen
def mysolutions(...):
....
Then, you can simply use it as is, for dissociating your I/O:
try:
for solution in mysolutions(...):
print(solution) #Probably needs some formatting
except RuntimeError:
print("I found no value (or there was some error somewhere...)")

how to embed ipython 0.12 so that it inherits namespace of the caller?

EDIT I isolated a real minimal example which does not work (it is a part of more complex code); the culprit is the inputhook part after all:
def foo():
exec 'a=123' in globals()
from IPython.frontend.terminal.embed import InteractiveShellEmbed
ipshell=InteractiveShellEmbed()
ipshell()
# without inputhook, 'a' is found just fine
import IPython.lib.inputhook
IPython.lib.inputhook.enable_gui(gui='qt4')
foo()
Running with 0.12:
In [1]: a
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
/tmp/<ipython-input-1-60b725f10c9c> in <module>()
----> 1 a
NameError: name 'a' is not defined
What would be the way around?
The problem is due to this call to InteractiveShell.instance() in the qt integration, when called before IPython is initialized. If this is called before your embedded shell is created, then some assumptions are not met. The fix is to create your embedded shell object first, then you shouldn't have any issue. And you can retrieve the same object from anywhere else in your code by simply calling InteractiveShellEmbed.instance().
This version should work just fine, by creating the InteractiveShellEmbed instance first:
from IPython.frontend.terminal.embed import InteractiveShellEmbed
# create ipshell *before* calling enable_gui
# it is important that you use instance(), instead of the class
# constructor, so that it creates the global InteractiveShell singleton
ipshell = InteractiveShellEmbed.instance()
import IPython.lib.inputhook
IPython.lib.inputhook.enable_gui(gui='tk')
def foo():
# without inputhook, 'a' is found just fine
exec 'a=123' in globals()
# all calls to instance() will always return the same object
ipshell = InteractiveShellEmbed.instance()
ipshell()
foo()

How can I assign sequences to constants in the CONSTANTS section of a TLA+ configuration file?

I've tried
CONSTANTS seq = <<5,6,7>>
but TLC gives me a syntax error:
Error: TLC found an error in the
configuration file at line 1. It was
expecting = or <- and didn't find it.
I've also tried to include the Sequences module in the configuration file, to no avail.
So... what do I have to do to assign a sequence?
I don't remember ever facing this problem and my TLC is too rusty to try and give you a first hand answer (I just restarted using the TLA+ toolbox).
From the post linked bellow, however, I figure that you can't instantiate constants with sequences through the TLC config files.
http://bbpress.tlaplus.net/topic/creating-a-sequence-from-a-set
Even though the question is old, leaving an answer may help future TLAers.
You can't directly assign to a constant in the TLA+ file. If you're using the toolbox, write CONSTANTS seq, then in the model add the tuple you want as an ordinary assignment.
So it turns out that you need a separate .tla file for that. Suppose you have "Main.tla" as you source file. You want MyConst to have value <<1,2,3>>. TLA+ toolbox generates MC.tla where it puts the constants:
---- MODULE MC ----
EXTENDS Main, TLC
const_uniq12345 = <<1,2,3>>
====
in MC.cfg, there will be the line
CONSTANT MyConst <- const_uniq12345
Note that MyConst = const_uniq12345 won't work -- if you use = instead of <-, MyConst will contain model value const_uniq12345 instead of <<1, 2, 3>>
I used https://github.com/hwayne/tlacli to be able to run TLC from command line (TLA toolbox has awful UX), and I was able to supply a tuple constant with help of extra .tla file like this. I used meaningful name instead of const_uniq12345 too, of course. Had to call java -cp /path/to/tla2tools.jar ... manually, though (got the full command using --show-script option of tlacli), because currently tlacli doesn't handle <- in the config.