calling a tcl proc in python3 - python-3.x

I am trying to call a tcl proc in a python program.
The tcl script starts with
proc scale_wigner-seitz_radii { } {
(I am not sure if I can put the full proc here, as this is a part of a licensed program).
This program is called by my python script:
#!/usr/bin/python3
import sys
from numpy import arange
from tempfile import mkstemp
from shutil import move, copy
from os import remove, close, mkdir, path
import Tkinter
def repll(file_path, pattern, subst):
print(pattern)
print(subst)
print(file_path)
r = Tkinter.Tk
# fullpath = str(subst) + "/" + file_path
fh, abs_path = mkstemp()
with open(abs_path, "w") as new_file:
with open(file_path, "r") as old_file:
for line in old_file:
new_file.write(line.replace(pattern.strip(),
str(subst).strip()))
r.tk.eval('source /home/rudra/WORK/xband/create_system_util.tcl')
r.tk.eval('proc scale_wigner-seitz_radii')
copy(abs_path, path.join(str(subst), file_path))
inpf = str(sys.argv[1])
a = []
print (inpf)
with open(inpf, "r") as ifile:
for line in ifile:
if line.startswith("lattice parameter A"):
a = next(ifile, "")
print(a)
for i in arange(float(a)-.10, float(a)+.10, 0.02):
if not path.exists(str(i)):
mkdir(str(i))
repll(inpf, a, i)
I havn't make a minimal example, because this seems better than explaining in english.
At the very end of def repll, it is calling the tcl proc. I have never encountered a tcl script before, and found the calling process from this question.
But when I am running this, I am getting error:
Traceback (most recent call last):
File "xband.py", line 41, in <module>
repll(inpf, a, i)
File "xband.py", line 24, in repll
r.tk.eval('source /home/rudra/WORK/xband/create_system_util.tcl')
AttributeError: class Tk has no attribute 'tk'
How I can solve this?
After Donal's Comment Thanks for your reply. After following your suggestion, I got same error from source line.
Traceback (most recent call last):
File "xband.py", line 41, in <module>
repll(inpf, a, i)
File "xband.py", line 24, in repll
r.tk.eval('/home/rudra/WORK/xband/create_system_util.tcl')
AttributeError: class Tk has no attribute 'tk'
Sorry if its silly, but since the tcl is in different file, I must source that first, right? And, as I said, this is the first tcl code I am looking at, please be elaborate.

The problem seems to be this line:
r = Tkinter.Tk
My guess is, you think this is creating an instance of Tk, but you're merely saving a reference to the class rather than creating an instance of the class. When you instantiate it, the object that gets returned has an attribute named tk, which the object internally uses to reference the tcl interpreter. Since you aren't instantiating it, r (which points to Tk) has no such attribute.
To fix it, instantiate the class by adding parenthesis:
r = Tkinter.Tk()
r will now be a proper reference to a Tk object, and should have a tk attribute, and with that you can call eval on raw tcl code.

Related

How to randomly copy the contents of a text document to my clipboard

This is my original question
The following script copies the text in /home/my_files/document1.txt to my clipboard.
import pyperclip
path = '/home/my_files/document1.txt'
The_text_of_the_file_that_will_be_copied = open(path, 'r').read()
pyperclip.copy(The_text_of_the_file_that_will_be_copied)
Let's say /home/my_files/ contains the following five documents:
/home/my_files/document1.txt
/home/my_files/document2.txt
/home/my_files/document3.txt
/home/my_files/image1.jpg
/home/my_files/image2.png
I would like to create a script to randomly copy the contents of one of the three text documents in /home/my_files/ to my clipboard.
Of course the following script does not work but it shows some of the modules I've been experimenting with.
import glob,random,pyperclip
pattern = "*.txt"
path = random.choice((glob.glob(pattern))("/home/my_files/"))
The_text_of_the_file_that_will_be_copied = open(path, 'r').read()
pyperclip.copy(The_text_of_the_file_that_will_be_copied)
Do you have any relevant suggestions for me?
I added the subsequent content to my original question above
When I tried the following solution which #Jacob Lee created...
import glob
import random
import pyperclip
files = [os.path.abspath(f) for f in glob.glob("./home/my_files")]
path = random.choice(files)
with open(path) as f:
pyperclip.copy(f.read())
I received the following error message...
Traceback (most recent call last):
File "abc.py", line 3, in <module>
path = random.choice(glob.glob(pattern))
File "/usr/lib/python3.8/random.py", line 290, in choice
raise IndexError('Cannot choose from an empty sequence') from None
IndexError: Cannot choose from an empty sequence
Someone else suggested the following script to me...
import glob,random,pyperclip
pattern = "/home/my_files/*.txt"
path = random.choice(glob.glob(pattern))
print("copying contents of ", path)
The_text_of_the_file_that_will_be_copied = open(path, 'r').read()
pyperclip.copy(The_text_of_the_file_that_will_be_copied)
But that script doesn't work either. I received the following error when I ran that script...
Traceback (most recent call last):
File "abc.py", line 3, in <module>
path = random.choice(glob.glob(pattern))
File "/usr/lib/python3.8/random.py", line 290, in choice
raise IndexError('Cannot choose from an empty sequence') from None
IndexError: Cannot choose from an empty sequence
I am confused.
The following successfully copies the entire contents of a random text file in /home/my_files/ to my clipboard
import glob,random,pyperclip
pattern = "/home/my_files/*.txt"
path = random.choice(glob.glob(pattern))
print("copying contents of ", path)
The_text_of_the_file_that_will_be_copied = open(path, 'r').read()
pyperclip.copy(The_text_of_the_file_that_will_be_copied)
Thanks to #Asocia
Thanks to #Asocia for insisting that the script above works correctly. I don't know what I had been doing wrong, but I must have been doing something wrong when I indicated the script above did not work properly.
You're code raises a TypeError: 'list' object is not callable exception when you try to assign path, in this line:
path = random.choice((glob.glob(pattern))("/home/my_files"))
glob.glob() returns a list (possibly empty). (Also, you put the glob.glob() call inside redundant parentheses.) Then, you try to call glob.glob()("/home/my_files/") (in essence, [...](), raising the TypeError exception.
import glob
import random
import pyperclip
files = [os.path.abspath(f) for f in glob.glob("./home/my_files/*.txt")]
path = random.choice(files)
with open(path) as f:
pyperclip.copy(f.read())

Python: copy file tree to a text file

I'm trying to create a text file with a tree of all files / dirs from a place that I choose using os.chdir(). My approach is to print the tree and to save all prints to the text file. The problem is that it doesn't copy the printed tree and the file is blank.
What am I doing wrong?
And is there a way to write this kind of data to the file without to actually print it?
My code:
import os
import sys
f = open("tree.txt", "w")
os.chdir("c:\\Users\Daniel\Desktop")
sys.stdout = f
os.system("tree /f")
f.close()
Edit
I was able to get the file tree from the clipboard after executing the command, however it gives me and eror when it tried to write to the txt file.
code:
import os
import tkinter
with open("tree.txt", "w") as f:
os.system("tree /f |clip")
root = tkinter.Tk()
tree = root.clipboard_get()
print(tree)
f.write(tree)
eror:
Traceback (most recent call last):
File "c:\Users\Daniel\Desktop\Tick\code_test\files.py", line 9, in <module>
f.write(tree)
File "C:\Users\Daniel\AppData\Local\Programs\Python\Python38-32\lib\encodings\cp1252.py", line 19, in encode
return codecs.charmap_encode(input,self.errors,encoding_table)[0]
UnicodeEncodeError: 'charmap' codec can't encode character '\u2502' in position 80: character maps to <undefined>
solution
So I found the problem, I needed to use codec to be able write unicode to the text file. Now it works very well
code:
import os
import tkinter
import codecs
with codecs.open("tree.txt", "w", "utf8") as f:
os.chdir("c:\\Users")
os.system("tree /f |clip")
root = tkinter.Tk()
tree = root.clipboard_get()
f.write(tree)
Method check_output from subprocess module can help you to catch program output:
import subprocess
f = open("tree.txt", "wb")
tree_output = subprocess.check_output('tree /f', shell=True, cwd=r'c:\Users\Daniel\Desktop')
f.write(tree_output)
f.close()
Or with context manager:
import subprocess
with open("tree.txt", "wb") as f:
f.write(subprocess.check_output('tree /f', shell=True, cwd=r'c:\Users\Daniel\Desktop'))
Option wb is required because check_output returns bytes not a str. If you want to process output like a string - call tree_output.decode() first.

Having trouble modifying python 2 code to python 3

I've been trying to translate python 2.7 code to python 3. I believe everything above checkpoint 1 should be correct. But I'm getting an error I associated with the second half. I can always download the file I need straight from the link, but I'd like to know what's breaking here.
import urllib
from urllib.request import urlopen
import tarfile
import os
path = 'https://www.cs.cmu.edu/~./enron/enron_mail_20150507.tar.gz'
url = urlopen(path)
#checkpoint 1
os.chdir('..')
tfile = tarfile.open(url, "r:gz")
tfile.extractall(".")
Error:
Traceback (most recent call last):
File "startup.py", line 43, in <module>
tfile = tarfile.open(url, "r:gz")
File "/anaconda3/lib/python3.6/tarfile.py", line 1589, in open
return func(name, filemode, fileobj, **kwargs)
File "/anaconda3/lib/python3.6/tarfile.py", line 1636, in gzopen
fileobj = gzip.GzipFile(name, mode + "b", compresslevel, fileobj)
File "/anaconda3/lib/python3.6/gzip.py", line 163, in __init__
fileobj = self.myfileobj = builtins.open(filename, mode or 'rb')
TypeError: expected str, bytes or os.PathLike object, not HTTPResponse
When confronted with an error like this, closely look at the traceback, and read the documentation for the functions and objects involved.
urllib.request.urlopen returns a HTTPResponse object.
If you look at the error message, you see that tarfile.open expects a str, bytes or os.PathLike object for the parameter name.
However, tarfile.open supports using a file object as a third argument fileobj, and HTTPResponse implements the io.BufferedIOBase interface. The classes in io are basically the file objects that the open function returns.
So you should be able to do this:
tfile = tarfile.open(None, "r:gz", files)
or
tarfile.open(fileobj=url, mode="r:gz")
The latter could be considered more Pythonic ("explicit is better than implicit").
os.chdir('..')
tfile = tarfile.open("enron_mail_20150507.tar.gz", "r:gz")
Instead of doing the above two steps, can you just mention the fully qualified file name as parameter to tarfile.open? just to rule out the possibility that the path is incorrect

System path check has TypeError: argument of type 'NoneType' is not iterable

Goal: To import files in a pretty manner
I have a piece of code (See Source) that attempts to load environment data (from a .env file) and then adding a specific configuration value to the system path. This supposedly enables me to import other files with the following format:
from evaluation.word_probability import WordFrequencyCounter
This allows me access a word_probability.py Python file from the evaluation folder using this notation, as seen in the last line of the source code below:
Source
#!/usr/bin/env python3
import sys
from dotenv import load_dotenv, find_dotenv
from os import environ
# Add python project root folder to python path
load_dotenv(find_dotenv(), override=True, verbose=False)
PYTHON_SCRIPTS_DIR = environ.get('PYTHON_SCRIPTS_DIR')
PROJECT_DIR = environ.get('PROJECT_DIR')
sys.path.insert(0, PYTHON_SCRIPTS_DIR)
from evaluation.word_probability import WordFrequencyCounter
The problem
The problem I'm encountering is that when I run my python script, it tells me that it could not iterate on a NoneType:
Error message
Traceback (most recent call last):
File "python/word_frequencies.py", line 13, in <module>
from evaluation.word_probability import WordFrequencyCounter
File "/Users/darrenkarlsapalo/git/thesis/thesis-nltk/python/evaluation/word_probability.py", line 16, in <module>
from nltk.corpus import stopwords
File "/Users/darrenkarlsapalo/.local/share/virtualenvs/thesis-nltk-QvwJevGq/lib/python3.6/site-packages/nltk/__init__.py", line 115, in <module>
from nltk.decorators import decorator, memoize
File "/Users/darrenkarlsapalo/.local/share/virtualenvs/thesis-nltk-QvwJevGq/lib/python3.6/site-packages/nltk/decorators.py", line 23, in <module>
sys.path = [p for p in sys.path if "nltk" not in p]
File "/Users/darrenkarlsapalo/.local/share/virtualenvs/thesis-nltk-QvwJevGq/lib/python3.6/site-packages/nltk/decorators.py", line 23, in <listcomp>
sys.path = [p for p in sys.path if "nltk" not in p]
TypeError: argument of type 'NoneType' is not iterable
How do I fix this? I just want my script to run but it's not continuing past the imports.
You can't iterate on a None.
The problem is descriptive enough: It is saying that it is trying to iterate through a non-iterable object. Specifically, the object you are trying to iterate is of the type NoneType: an instance of None.
In this specific scenario, the loop is defined as:
sys.path = [p for p in sys.path if "nltk" not in p]
In this example, each path denoted by p is iterated from the list sys.path. However, the string "nltk" could not be found in p on the case where p = None. Remember, None is not an iterable type. There shouldn't be any None instances in the system path.
Where did the None come from?
Because we are working with the sys.path list, quickly inspecting the values of sys.path reveals that to make sense:
[None, '/Users/darrenkarlsapalo/git/thesis/thesis-nltk/python', '/Users/darrenkarlsapalo/.local/share/virtualenvs/thesis-nltk-QvwJevGq/lib/python36.zip', '/Users/darrenkarlsapalo/.local/share/virtualenvs/thesis-nltk-QvwJevGq/lib/python3.6', '/Users/darrenkarlsapalo/.local/share/virtualenvs/thesis-nltk-QvwJevGq/lib/python3.6/lib-dynload', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6', '/Users/darrenkarlsapalo/.local/share/virtualenvs/thesis-nltk-QvwJevGq/lib/python3.6/site-packages']
At the head of the list, there is a None instance in the script. In that case, there was some piece of code that inserted None into the system path. By checking the source code again, it easily shows that we did not check whether the configuration file did indeed have a value.
Solution
#!/usr/bin/env python3
import sys
from dotenv import load_dotenv, find_dotenv
from os import environ
# Add python project root folder to python path
load_dotenv(find_dotenv(), override=True, verbose=False)
PYTHON_SCRIPTS_DIR = environ.get('PYTHON_SCRIPTS_DIR')
PROJECT_DIR = environ.get('PROJECT_DIR')
# CHECK FIRST WHETHER IT IS NOT NONE BEFORE ADDING
if PYTHON_SCRIPTS_DIR is not None:
sys.path.insert(0, PYTHON_SCRIPTS_DIR)
from evaluation.word_probability import WordFrequencyCounter
Simply checking if the value is not None before adding to the system path fixes the problem.

Error when Unzipping with Pyside Qtgui

When I run my program, I get the following error and am not sure on how to correct it. Can someone help with explaining what this error is and how to correct it? Newb here so details are appreciated. Thanks for your time in advance!
Code:
#!/usr/bin/python
import zipfile
from PySide import QtGui
import re
#Select file to extract
app = QtGui.QApplication([])
dialog = QtGui.QFileDialog()
dialog.setFileMode(QtGui.QFileDialog.AnyFile)
if (dialog.exec()):
fileName = dialog.selectedFiles()
#Select Directory to extract to
dialog = QtGui.QFileDialog()
dialog.setFileMode(QtGui.QFileDialog.Directory)
dialog.setOption(QtGui.QFileDialog.ShowDirsOnly)
if (dialog.exec()):
dirName = dialog.selectedFiles()
print("Extracting.....")
zFile= zipfile.ZipFile(fileName)
zFile.extractall(dirName)
Error output:
Traceback (most recent call last):
File "C:\Users\Jennifer\Documents\BatchScripts\unzip.py", line 22, in <module>
zFile= zipfile.ZipFile(fileName)
File "C:\Python33\lib\zipfile.py", line 933, in __init__
self._RealGetContents()
File "C:\Python33\lib\zipfile.py", line 970, in _RealGetContents
endrec = _EndRecData(fp)
File "C:\Python33\lib\zipfile.py", line 237, in _EndRecData
fpin.seek(0, 2)
AttributeError: 'list' object has no attribute 'seek'
In your file and target directory code blocks, dialog.selectedFiles() returns a list. zipfile.ZipFile can only handle one file at a time, hence your error. To iterate over the list being provided by dialog.selectedFiles(), use the following:
for archive in fileName: # you should probably change it to fileNames to reflect its true nature
zfile = zipfile.ZipFile(archive)
print("Extracting " + str(zfile.filename) + "...")
zfile.extractall(dirName[0]) # also a list, extract to first item and ignore rest
and you should be all set.

Resources