Cannot run a python script in a Linux terminal - python

I am running a rocky9 Linux terminal and trying to download/clone a git repo. This works, but when trying to plot a graph using the following python script, nothing happens. It works fine on Windows, but the graph does not pop up or display in the terminal.
Heres the Py script:
import matplotlib.pyplot as plt
import numpy as np
# create a dictionary of data from a file in csv format
def createData(filename):
data = {}
with open(filename) as f:
for line in f:
(key, val) = line.split(',')
data[int(key)] = int(val)
return data
def plotData(data):
x = []
y = []
for key in data:
x.append(key)
y.append(data[key])
plt.plot(x,y)
plt.show(block=True)
plots = createData('graphPlots.txt')
plotData(plots)
The graphPlots.txt file is indeed in the same dir and has the following contents:
2,2400
3,2900
4,2800
5,4300
6,8100
7,20300
8,28400
9,41000
10,31600
11,34900
12,52700
13,58200
14,69600
15,85400
16,131200
17,124900
.....
This does change due to another Java file running, but I think the Python script is the issue. Any help is appreciated.
I found a similar solution stating I needed to add the "block=True" parameter to the plt.show. I tried this but this didn't work either.

Related

Can you edit a .py script from another?

I'm creating a similarity program that calculates the euclidean distance of images, I'm looking for user input so that if they want to use a portion of the code, they can choose so. in that case, a line (specifically 13 in dc2.py) needs to be changed to " ". How can i go about this?
I've attempted using the open function alongside .write, opening a file though open(dc.py).read(), and to no avail.
This converts the image into an array (program dc2.py):
import numpy as np
import imageio
from numpy import array
img = imageio.imread("Machine Screw.jpg")
data = array(img)
with open('test2.txt', 'w') as outfile:
np.savetxt(outfile, data_slice, fmt='%-7.2f')
exec(open("Halfer.py").read())
Here's the failed code to change the previous .py:
inp = input("Want to use halfer?: ")
if inp == 'y':
the_file = open('dc2.py', 'a')
the_file[13].write(' ')
--------------------------------------
I expected:
Process finished with exit code 0
here's what actually happened:
Traceback (most recent call last):
File "C:/Users/User/Desktop/PySimCode/Resources/Ini.py", line 5, in <module>
the_file[13].write(' ')
TypeError: '_io.TextIOWrapper' object is not subscriptable
Thank you for all the help!
Your solution what you want to implement is not too "Pythonic". In my opinion you should import dc2.py file as module to Ini.py script and use parameters based on user-input to manipulate the behavior of dc2.py script.
For example:
dc2.py
import numpy as np
import imageio
import subprocess
from numpy import array
def image_converter(halfer_needed=True):
img = imageio.imread("Machine Screw.jpg")
data = array(img)
with open('test2.txt', 'w') as outfile:
np.savetxt(outfile, data, fmt='%-7.2f')
if halfer_needed:
sp = subprocess.Popen(["python", "Halfer.py"]) # Call Halfer.py script
ret_stdout, ret_stderr = sp.communicate() # These variables contain the STDOUT and STDERR
ret_retcode = sp.returncode # This variable conains the return code of your command
I think you want to call the Halfer.py script if user wants it so I have used the subprocess module to call this script as you can see above. You can see more details and options about this module: https://docs.python.org/3/library/subprocess.html
Ini.py
from dc2 import image_converter # Import your function from "dc2.py" script
inp = str(input("Want to use halfer?: "))
if inp == 'y':
image_converter(halfer_needed=False)
image_converter() # you don't need to define the keyword argument because the default value is True.
Try this:
inp = raw_input("Want to use halfer?: ")
if inp == 'y':
origin_file = open('dc2.py','r').readlines()
the_file = open('dc2.py','w')
origin_file[12] = '\n'
for line in origin_file:
the_file.write(line)
the_file.close()
Some notes I'd like to add:
input reads a block of text and parses it. You should probably always use raw_input.
open does different things, depending on the mode parameter. In my case, I used r for reading, then w for writing. (I don't think there's a way to read and write on the same <open> object). a is append, which only lets you add lines. Read here
To get the contents from an <open>, use .read() or .readlines().
The 13th line is index 12. Also, I changed it to '\n' instead of ' '.
Don't forget to call .close() on your <open> when you are done with it!
Hope this works for you!
You can, but you shouldn't.
You are trying to activate some code based on uer imput, this is doable encapsulating the code in functions, that you can import and axecute based on a condition.
You are trying to achieve this result by reading files and executing them manually, basically you are doing what the Python interpreter should do..
First, you need to chage you modules to something that activates at will, not as soon as the file is loaded, for instance your dc2.py would look like this:
import numpy as np
import imageio
from numpy import array
import Halfer # <- here you import the py file, not open and read
def run(use_halfer):
img = imageio.imread("Machine Screw.jpg")
data = array(img)
with open('test2.txt', 'w') as outfile:
np.savetxt(outfile, data_slice, fmt='%-7.2f')
if use_halfer:
Halfer.run()
..and your Halfer.py file should look like this:
def run():
# ..all your Halfer.py code here inside the run function
..and then your starting point of the script can look like:
import dc2
inp = input("Want to use halfer?: ")
dc2.run(inp == 'y') # <- here you tell dc2 to use halfer or not.

import python module when launching from VBA

It is the first time I write as I really didn't find any solution to my issue.
I want to allow my user to launch some Python program from Excel.
So i have this VBA code at some point:
lg_ErrorCode = wsh.Run(str_PythonPath & " " & str_PythonArg, 1, bl_StopVBwhilePython)
If lg_ErrorCode <> 0 Then
MsgBox "Couldn't run python script! " _
+ vbCrLf + CStr(lg_ErrorCode)
Run_Python = False
End If
str_PythonPath = "C:\Python34\python.exe C:\Users\XXXX\Documents\4_Python\Scan_FTP\test.py"
str_PythonArg = "arg1 arg2"
After multiple testing, the row in error in Python is when I try to import another module (I precise that this VBA code is working without the below row in Python):
import fct_Ftp as ftp
The architecture of the module is as follow:
4_Python
-folder: Scan_FTP
- file: test.py (The one launch from VBA)
-file: fct_Ftp.py
(For information, I change the architecture of the file, and try to copy the file at some other position just to test without success)
The import has no problem when I launch Test.py directly with:
import sys, os
sys.path.append('../')
But from VBA, this import is not working.
So I figured out this more generic solution, that dont work as well from Excel/VBA
import sys, os
def m_importingFunction():
str_absPath = os.path.abspath('')
str_absPathDad = os.path.dirname(str_absPath)
l_absPathSons = [os.path.abspath(x[0]) for x in os.walk('.')]
l_Dir = l_absPathSons + [str_absPathDad]
l_DirPy = [Dir for Dir in l_Dir if 'Python' in Dir]
for Dir in l_DirPy:
sys.path.append(Dir)
print(Dir)
m_importingFunction()
try:
import fct_Ftp as ftp
# ftp = __import__ ("fct_Ftp")
write += 'YAAAA' # write a file YAAAA from Python
except:
write += 'NOOOOOO' # write a file NOOOOO from VBA
f= open(write + ".txt","w+")
f.close()
Can you please help me as it is a very tricky questions ?
Many thanks to you guys.
You are able to start your program from the command line?
Why not create a batch file with excel which you then start in a shell?

display dns cache in windows

I'm trying to display windows cache and the only way I found is using subprocess through command line to display the cache. Is there any library that helps collect such data from windows rather than using cmd.exe or Should just I stick with the command line.
import subprocess
import os
def _list_dns_cache():
values = {}
# values['HostNames']=[]
values['hostvalues']=[]
cache = os.popen2("ipconfig /displaydns")
source = cache[1].read()
for row in source.split('\n'):
if ': ' in row:
key, value = row.split(': ')
key1 = row.split('..')[0]
values['hostvalues'].append({'key':key1 ,'value':value})
return values

Python file does not run on Ubuntu on server but runs in local on Mac

This is the code where I'm dumping all the data from .csv file into mongodb. What is strange is that it runs perfectly well on my mac but when I upload this code to Windows Azure running ubuntu 12.04.3 LTS only the main code gets executed and function is not called. Here's the code I'm using
import csv,json,glob,traceback
from pymongo import MongoClient
import datetime
import sys
import string
def make_document(column_headers,columns,timestamps):
#assert len(column_headers)==len(columns)
lotr = filter(lambda x: x[0] is not None,zip(column_headers,columns))
final = []
#print lotr
if not timestamps=={}:
for k,v in lotr:
try:
tformat = timestamps[k]
time_val = datetime.datetime.strptime(v,tformat)
final.append((k,time_val))
except KeyError:
final.append((k,v))
return dict(final)
else:
return dict(lotr)
def keep_printable_only(s):
return filter(lambda x: x in string.printable,s)
def perform(conf):
client = MongoClient(conf["server"],conf["port"])
db = client[conf["db"]]
collection = db[conf["collection"]]
files = glob.glob(conf["data_form"])
column_headers = conf["columns"]
csv_opts = {}
for k,v in conf["csv_options"].items():
csv_opts[str(k)]=str(v)
for infile in files:
#print conf["csv_options"]
inCSV = csv.reader(open(infile,'rU'),**csv_opts)
counter = 0
for record in inCSV:
yield record
counter +=1
if counter==2:
print record
#sys.exit(0)
record= map(keep_printable_only,record)
try:
doc = make_document(column_headers,record,conf["timestamp_columns"])
collection.insert(doc)
except :
print "error loading one of the lines : "
print traceback.format_exc()
if __name__=='__main__':
print"reads all data files of same format as given in column mapping and dumps them to a mongo collection"
print "uses conf.json.test as config file"
conf = json.load(open('./conf.json.txt'))
for row in perform(conf):
record= map(keep_printable_only,row)
When I run this on Azure, mongo collection is not created and the code terminates after printing the two lines in main code. I have no idea as to why this is happening.
Debug output would be very useful, in the form of a stack trace, as commented by #Alfe.
Further than that, it looks like your code stops at the line where you try to access a local file to read the configuration. Make sure that you can access the filesystem that way in Azure; sometimes providers put very strict walls between your code and the actual machine.
You can make your code more portable by using:
import os
import os.path
conf_filehandle = open(os.path.join(os.getcwd(), 'conf.json'))
conf = json.load(conf_filehandle)
Of course, you should also make sure that you have uploaded the JSON file to Azure :)

How do I get the current IPython / Jupyter Notebook name

I am trying to obtain the current NoteBook name when running the IPython notebook. I know I can see it at the top of the notebook. What I am after something like
currentNotebook = IPython.foo.bar.notebookname()
I need to get the name in a variable.
adding to previous answers,
to get the notebook name run the following in a cell:
%%javascript
IPython.notebook.kernel.execute('nb_name = "' + IPython.notebook.notebook_name + '"')
this gets you the file name in nb_name
then to get the full path you may use the following in a separate cell:
import os
nb_full_path = os.path.join(os.getcwd(), nb_name)
I have the following which works with IPython 2.0. I observed that the name of the notebook is stored as the value of the attribute 'data-notebook-name' in the <body> tag of the page. Thus the idea is first to ask Javascript to retrieve the attribute --javascripts can be invoked from a codecell thanks to the %%javascript magic. Then it is possible to access to the Javascript variable through a call to the Python Kernel, with a command which sets a Python variable. Since this last variable is known from the kernel, it can be accessed in other cells as well.
%%javascript
var kernel = IPython.notebook.kernel;
var body = document.body,
attribs = body.attributes;
var command = "theNotebook = " + "'"+attribs['data-notebook-name'].value+"'";
kernel.execute(command);
From a Python code cell
print(theNotebook)
Out[ ]: HowToGetTheNameOfTheNoteBook.ipynb
A defect in this solution is that when one changes the title (name) of a notebook, then this name seems to not be updated immediately (there is probably some kind of cache) and it is necessary to reload the notebook to get access to the new name.
[Edit] On reflection, a more efficient solution is to look for the input field for notebook's name instead of the <body> tag. Looking into the source, it appears that this field has id "notebook_name". It is then possible to catch this value by a document.getElementById() and then follow the same approach as above. The code becomes, still using the javascript magic
%%javascript
var kernel = IPython.notebook.kernel;
var thename = window.document.getElementById("notebook_name").innerHTML;
var command = "theNotebook = " + "'"+thename+"'";
kernel.execute(command);
Then, from a ipython cell,
In [11]: print(theNotebook)
Out [11]: HowToGetTheNameOfTheNoteBookSolBis
Contrary to the first solution, modifications of notebook's name are updated immediately and there is no need to refresh the notebook.
As already mentioned you probably aren't really supposed to be able to do this, but I did find a way. It's a flaming hack though so don't rely on this at all:
import json
import os
import urllib2
import IPython
from IPython.lib import kernel
connection_file_path = kernel.get_connection_file()
connection_file = os.path.basename(connection_file_path)
kernel_id = connection_file.split('-', 1)[1].split('.')[0]
# Updated answer with semi-solutions for both IPython 2.x and IPython < 2.x
if IPython.version_info[0] < 2:
## Not sure if it's even possible to get the port for the
## notebook app; so just using the default...
notebooks = json.load(urllib2.urlopen('http://127.0.0.1:8888/notebooks'))
for nb in notebooks:
if nb['kernel_id'] == kernel_id:
print nb['name']
break
else:
sessions = json.load(urllib2.urlopen('http://127.0.0.1:8888/api/sessions'))
for sess in sessions:
if sess['kernel']['id'] == kernel_id:
print sess['notebook']['name']
break
I updated my answer to include a solution that "works" in IPython 2.0 at least with a simple test. It probably isn't guaranteed to give the correct answer if there are multiple notebooks connected to the same kernel, etc.
It seems I cannot comment, so I have to post this as an answer.
The accepted solution by #iguananaut and the update by #mbdevpl appear not to be working with recent versions of the Notebook.
I fixed it as shown below. I checked it on Python v3.6.1 + Notebook v5.0.0 and on Python v3.6.5 and Notebook v5.5.0.
import jupyterlab
if jupyterlab.__version__.split(".")[0] == "3":
from jupyter_server import serverapp as app
key_srv_directory = 'root_dir'
else :
from notebook import notebookapp as app
key_srv_directory = 'notebook_dir'
import urllib
import json
import os
import ipykernel
def notebook_path(key_srv_directory, ):
"""Returns the absolute path of the Notebook or None if it cannot be determined
NOTE: works only when the security is token-based or there is also no password
"""
connection_file = os.path.basename(ipykernel.get_connection_file())
kernel_id = connection_file.split('-', 1)[1].split('.')[0]
for srv in app.list_running_servers():
try:
if srv['token']=='' and not srv['password']: # No token and no password, ahem...
req = urllib.request.urlopen(srv['url']+'api/sessions')
else:
req = urllib.request.urlopen(srv['url']+'api/sessions?token='+srv['token'])
sessions = json.load(req)
for sess in sessions:
if sess['kernel']['id'] == kernel_id:
return os.path.join(srv[key_srv_directory],sess['notebook']['path'])
except:
pass # There may be stale entries in the runtime directory
return None
As stated in the docstring, this works only when either there is no authentication or the authentication is token-based.
Note that, as also reported by others, the Javascript-based method does not seem to work when executing a "Run all cells" (but works when executing cells "manually"), which was a deal-breaker for me.
The ipyparams package can do this pretty easily.
import ipyparams
currentNotebook = ipyparams.notebook_name
On Jupyter 3.0 the following works. Here I'm showing the entire path on the Jupyter server, not just the notebook name:
To store the NOTEBOOK_FULL_PATH on the current notebook front end:
%%javascript
var nb = IPython.notebook;
var kernel = IPython.notebook.kernel;
var command = "NOTEBOOK_FULL_PATH = '" + nb.base_url + nb.notebook_path + "'";
kernel.execute(command);
To then display it:
print("NOTEBOOK_FULL_PATH:\n", NOTEBOOK_FULL_PATH)
Running the first Javascript cell produces no output.
Running the second Python cell produces something like:
NOTEBOOK_FULL_PATH:
/user/zeph/GetNotebookName.ipynb
Yet another hacky solution since my notebook server can change. Basically you print a random string, save it and then search for a file containing that string in the working directory. The while is needed because save_checkpoint is asynchronous.
from time import sleep
from IPython.display import display, Javascript
import subprocess
import os
import uuid
def get_notebook_path_and_save():
magic = str(uuid.uuid1()).replace('-', '')
print(magic)
# saves it (ctrl+S)
display(Javascript('IPython.notebook.save_checkpoint();'))
nb_name = None
while nb_name is None:
try:
sleep(0.1)
nb_name = subprocess.check_output(f'grep -l {magic} *.ipynb', shell=True).decode().strip()
except:
pass
return os.path.join(os.getcwd(), nb_name)
There is no real way yet to do this in Jupyterlab. But there is an official way that's now under active discussion/development as of August 2021:
https://github.com/jupyter/jupyter_client/pull/656
In the meantime, hitting the api/sessions REST endpoint of jupyter_server seems like the best bet. Here's a cleaned-up version of that approach:
from jupyter_server import serverapp
from jupyter_server.utils import url_path_join
from pathlib import Path
import re
import requests
kernelIdRegex = re.compile(r"(?<=kernel-)[\w\d\-]+(?=\.json)")
def getNotebookPath():
kernelId = kernelIdRegex.search(get_ipython().config["IPKernelApp"]["connection_file"])[0]
for jupServ in serverapp.list_running_servers():
for session in requests.get(url_path_join(jupServ["url"], "api/sessions"), params={"token": jupServ["token"]}).json():
if kernelId == session["kernel"]["id"]:
return Path(jupServ["root_dir"]) / session["notebook"]['path']
Tested working with
python==3.9
jupyter_server==1.8.0
jupyterlab==4.0.0a7
Modifying #jfb method, gives the function below which worked fine on ipykernel-5.3.4.
def getNotebookName():
display(Javascript('IPython.notebook.kernel.execute("NotebookName = " + "\'"+window.document.getElementById("notebook_name").innerHTML+"\'");'))
try:
_ = type(NotebookName)
return NotebookName
except:
return None
Note that the display javascript will take some time to reach the browser, and it will take some time to execute the JS and get back to the kernel. I know it may sound stupid, but it's better to run the function in two cells, like this:
nb_name = getNotebookName()
and in the following cell:
for i in range(10):
nb_name = getNotebookName()
if nb_name is not None:
break
However, if you don't need to define a function, the wise method is to run display(Javascript(..)) in one cell, and check the notebook name in another cell. In this way, the browser has enough time to execute the code and return the notebook name.
If you don't mind to use a library, the most robust way is:
import ipynbname
nb_name = ipynbname.name()
If you are using Visual Studio Code:
import IPython ; IPython.extract_module_locals()[1]['__vsc_ipynb_file__']
Assuming you have the Jupyter Notebook server's host, port, and authentication token, this should work for you. It's based off of this answer.
import os
import json
import posixpath
import subprocess
import urllib.request
import psutil
def get_notebook_path(host, port, token):
process_id = os.getpid();
notebooks = get_running_notebooks(host, port, token)
for notebook in notebooks:
if process_id in notebook['process_ids']:
return notebook['path']
def get_running_notebooks(host, port, token):
sessions_url = posixpath.join('http://%s:%d' % (host, port), 'api', 'sessions')
sessions_url += f'?token={token}'
response = urllib.request.urlopen(sessions_url).read()
res = json.loads(response)
notebooks = [{'kernel_id': notebook['kernel']['id'],
'path': notebook['notebook']['path'],
'process_ids': get_process_ids(notebook['kernel']['id'])} for notebook in res]
return notebooks
def get_process_ids(name):
child = subprocess.Popen(['pgrep', '-f', name], stdout=subprocess.PIPE, shell=False)
response = child.communicate()[0]
return [int(pid) for pid in response.split()]
Example usage:
get_notebook_path('127.0.0.1', 17004, '344eb91bee5742a8501cc8ee84043d0af07d42e7135bed90')
To realize why you can't get notebook name using these JS-based solutions, run this code and notice the delay it takes for the message box to appear after python has finished execution of the cell / entire notebook:
%%javascript
function sayHello() {
alert('Hello world!');
}
setTimeout(sayHello, 1000);
More info
Javascript calls are async and hence not guaranteed to complete before python starts running another cell containing the code expecting this notebook name variable to be already created... resulting in NameError when trying to access non-existing variables that should contain notebook name.
I suspect some upvotes on this page became locked before voters could discover that all %%javascript-based solutions ultimately don't work... when the producer and consumer notebook cells are executed together (or in a quick succession).
All Json based solutions fail if we execute more than one cell at a time
because the result will not be ready until after the end of the execution
(its not a matter of using sleep or waiting any time, check it yourself but remember to restart kernel and run all every test)
Based on previous solutions, this avoids using the %% magic in case you need to put it in the middle of some other code:
from IPython.display import display, Javascript
# can have comments here :)
js_cmd = 'IPython.notebook.kernel.execute(\'nb_name = "\' + IPython.notebook.notebook_name + \'"\')'
display(Javascript(js_cmd))
For python 3, the following based on the answer by #Iguananaut and updated for latest python and possibly multiple servers will work:
import os
import json
try:
from urllib2 import urlopen
except:
from urllib.request import urlopen
import ipykernel
connection_file_path = ipykernel.get_connection_file()
connection_file = os.path.basename(connection_file_path)
kernel_id = connection_file.split('-', 1)[1].split('.')[0]
running_servers = !jupyter notebook list
running_servers = [s.split('::')[0].strip() for s in running_servers[1:]]
nb_name = '???'
for serv in running_servers:
uri_parts = serv.split('?')
uri_parts[0] += 'api/sessions'
sessions = json.load(urlopen('?'.join(uri_parts)))
for sess in sessions:
if sess['kernel']['id'] == kernel_id:
nb_name = os.path.basename(sess['notebook']['path'])
break
if nb_name != '???':
break
print (f'[{nb_name}]')
just use ipynbname , which is practical
import ipynbname
nb_fname = ipynbname.name()
nb_path = ipynbname.path()
print(f"{nb_fname=}")
print(f"{nb_path=}")
I found this in https://stackoverflow.com/a/65907473/15497427

Categories

Resources