I have sample Jython code for JavaFX like this:
# hello.py
from javafx.application import Application
from javafx.scene import Scene
import javafx.scene.control
from javafx.scene.layout import AnchorPane
class Hello(Application):
def start(self, stage):
stage.setTitle("Hello, World!")
root = AnchorPane()
label = javafx.scene.control.Label("Hello, World!")
root.getChildren().add(label)
scene = Scene(root, 100, 40)
stage.setScene(scene)
stage.show()
if __name__ == '__main__':
Application.launch(Hello().class, [])
Here, I can do import javafx.scene.control and later use it like javafx.scene.control.Label("Hello, World!") but why can't I do from javafx.scene.control import Label?
Here's Jython info:
$ jython
Jython 2.5.3 (2.5:c56500f08d34+, Aug 13 2012, 14:48:36)
[Java HotSpot(TM) 64-Bit Server VM (Oracle Corporation)] on java1.8.0_25
Type "help", "copyright", "credits" or "license" for more information.
>>>
If you move your from/import statement inside of your start method, immediately before you need the Label control, I bet your code will work.
With Jython running on JavaFX8, there are certain things that you cannot do (such as import controls) until the JavaFX runtime has been started. (JavaFX2 was not this picky.) For this reason, starting the JavaFX runtime is the very first thing your Jython/JavaFX program should do. (I have a module specifically for doing this.) Then you can import everything else.
As an aside, I do not think you want to use the from/import approach, but rather the import/as approach. The former defeats caching, while the latter does not.
Related
Test.py:
def test():
print("Hello World")
test()
When I run this using the interpreter (ctrl+shift+p > Python: Select Interpreter > target interpreter), it works.
If I then try to run the repl (ctrl+shift+p > Python: Start REPL), I see the repl started in the terminal:
PS C:\Development\personal\python\GettingStarted> & c:/Development/personal/python/GettingStarted/.venv/Scripts/python.exe
Python 3.8.3 (tags/v3.8.3:6f8c832, May 13 2020, 22:20:19) [MSC v.1925 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
However, if I try to execute the defined method in the repl, I get an undefined error:
>>> test()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'test' is not defined
Correct way #1 to import and use:
>>> import test
Hello World
>>> test.test()
Hello World
Correct way #2 to import and use:
>>> from test import test
Hello World
>>> test()
Hello World
If you get an ImportError for both ways above, then you are running the Python REPL from the wrong directory.
It's a bit confusing that the filename and function name are the same.
Also it's a bit unusual that there is a call to test() at the end of the file (causing the function to be called at import time). Typically it's wrapped like if __name__ == '__main__': test() to avoid the call at import time, but make the call when run as a script from the command-line.
Import test doesn't work, because Python keywords are lowercase and case sensitive.
from test import Test doesn't work, because Python identifiers (e.g. function names) are case sensitive.
import Test may work on Windows (but not on macOS, Linux and many other operating systems), because filenames on Windows are case insensitive.
import test.py doesn't work, because it's not allowed to have the .py extension as part of the import module name.
import test from test doesn't work, because from ... must come before import ....
I need to import a single class (not the whole file) from a python file starting with number.
There was a topic on importing a whole module and it works, but can't find my way around this one.
(In python, how to import filename starts with a number)
Normally it would be:
from uni_class import Student
though the file is called 123_uni_class.
Tried different variations of
importlib.import_module("123_uni_class")
and
uni_class=__import__("123_uni_class")
Error:
from 123_uni_class import Student
^
SyntaxError: invalid decimal literal
importlib.import_module("123_uni_class") returns the module after importing it, you must give it a valid name in order to reuse it:
import importlib
my_uni_class = importlib.import_module("123_uni_class")
Then you can access your module under the name 'my_uni_class'.
This would be equivalent to import 123_uni_class as my_uni_class if 123_uni_class were valid in this context.
It works for me:
Python 3.6.8 (default, Feb 14 2019, 22:09:48)
[GCC 7.4.0] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import importlib
>>> importlib.import_module('123_a')
<module '123_a' from '/path/to/123_a.py'>
>>> __import__('123_a')
<module '123_a' from '/path/to/123_a.py'>
You would not see an actual syntax error containing the literal text "from 123_uni_class import ..." unless you actually have some source code containing that line.
If you must, you can also bypass the import system entirely by reading the contents of the file and exec()-ing them, possibly into a namespace you provide. For example:
mod = {}
with open('123_uni_class.py') as fobj:
exec(fobj.read(), mod)
Student = mod['Student']
This general technique is used, for example, to read config files written in Python and things like that. I would discourage it though for normal usage and suggest you just use a valid module name.
In my project, I am trying to share a global variable across modules as described in the Python documentation: https://docs.python.org/3/faq/programming.html#how-do-i-share-global-variables-across-modules
I seemed to find, however, that the global variable is instantiated twice and I am not sure why. I want the variable to be a singleton.
I was able to reproduce the issue with this minimal example:
# main.py
class TheClass:
def __init__(self):
print("init TheClass")
def do_work(self):
import worker
worker.do_work()
the_class:TheClass = TheClass()
if __name__ == '__main__':
the_class.do_work()
# worker.py
from main import the_class
def do_work():
print("doing work...")
Output of python main.py:
init TheClass
init TheClass
doing work...
'init TheClass' is logged twice which implies that the class was instantiated twice.
I was unable to reproduce this behaviour in the interactive Python shell:
Python 3.7.4 (tags/v3.7.4:e09359112e, Jul 8 2019, 20:34:20) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import main
init TheClass
>>> main.the_class.do_work()
doing work...
>>>
How do I fix this undesired behaviour?
This happens because you are having a circular import and because of something special that happens with the codefile that you are actually starting.
If you start a file (as the argument to python) it will become the __main__ module independent of its filename. If at a later point in time the same file is imported, it is not recognized as already imported and is reimported under its real name, main in your case. This is why the code is run twice. A third import will not rerun the code.
You can fix it by preventing circular imports (don't put stuff to import into the starter), or by putting the code that should not run twice into the name checking if you already have.
This question already has answers here:
from ... import OR import ... as for modules
(6 answers)
Closed 4 years ago.
I've always used from a import b but recently a team at work decided to move a module into a new namespace, and issued a warning notice telling people to replace import b with import a.b as b.
I've never used import as and the only documentation I can find seems to suggest it doesn't support import a.b as b, though clearly it does.
but is there actually a difference, and if so what?
As far as I know, correct me if I am wrong.
First, import a.b must import a module(a file) or a package(a directory contains __init__.py).
For example, you can import tornado.web as web but you cannot import flask.Flask as Flask as Flask is an object in package flask.
Second, import a.b also import the namespace a which from a import b won't. You can check it by globals().
So what's the influence? For example:
import tornado.web as web
Now you have access to namespace tornado, but you cannot access tornado.options even though tornado has this module. But as python's global package management, if you from tornado import options, you will not only get access to options but also add it to namespace tornado. So now you can also access options by tornado.options.
I am going to provide only a partial answer, and I will speculate a bit.
1) Sometimes I have observed that the second way works while the first does not. On my system:
Python 3.6.3 (default, Oct 3 2017, 21:45:48)
[GCC 7.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from tensorflow import keras # <- this works
>>>
>>> import tensorflow.keras as K # <- this fails
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'tensorflow.keras'
>>>
2) I usually don't see a difference between these two approaches to importing. I haven't investigated WHY there is a difference with TensorFlow. It may have to do with what names are imported to the top level by the various TensorFlow subfolder init.py files (which are completely empty in most cases, but the one in ../dist_packages/tensorflow/python is pretty long).
I am running python 3.6.4 (anaconda, spyder).
Do I need to reload a user-defined module in order to capture the changes?
For example, suppose I wrote the simple function and save it in test.py file:
def plus5(x):
return x + 5
Then in the IPython console I type
import test as t
and then I change the user-defined function to:
def plus5(x):
return x + 500
Then when I type in IPython console
t.plus5(0)
it returns 500 without re-importing or reloading the module first.
If I change the function name from plus5 to something else then I have to re-import the module to see the change. But when I change the function statements then it automatically captures the changes without re-importing the module
From the Python documentation:
Note: For efficiency reasons, each module is only imported once per interpreter session. Therefore, if you change your modules, you must restart the interpreter – or, if it’s just one module you want to test interactively, use importlib.reload()
e.g. import importlib; importlib.reload(modulename).
This is a feature in the IPython interpreter name autoreload. It has the magic command %autoreload which allows for activating or deactivating this feature. It seems to be on by default, but I was not able to find something proving that.
As Megalng explained, this is a built in feature of IPython interpreter and in default Python interpreter you have to use importlib to reload the module. Here is default python interpreter execution,
Python 3.6.2 (default, Sep 5 2017, 17:37:49)
[GCC 4.6.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>>
>>>
>>> import test as t
>>> t.plus5(0)
5
>>>
>>>
>>> #Changed function body to return x + 500
...
>>> t.plus5(0)
5
>>> import test as t
>>> t.plus5(0)
5
>>> #It had no affect, even importing again doesn't work.
...
>>> import importlib; importlib.reload(t)
<module 'test' from '~/test.py'>
>>>
>>> t.plus5(0)
500
>>> #Now it works !
...
>>>
As you can see, even after changing function body to return x + 500, it still generated a result of 5 for t.plus5(0), even importing test module again did not help. It only started working when importlib was used to reload test module.