How to get random value from a file in python? - file

It would have been very gratifying to figure this out by myself but I haven't been able to.
I want to grab a random value from a text file that contains data in the form of a dictionary eg:
{'One': '1111111', 'Two': '2222222', 'Three': '3333333'}
I've tried a few variations, but code is currently:
from random import *
table = open('file.txt')
random_value = random.choice(table.values())
When I try and print 'random_value' (to see if it is working), I get the error:
AttributeError: 'file' object has no attribute 'values'

table is a file object, and thus you want to turn it into a dictionary. Here I use the ast module:
from random import choice # No need to import everything if you're going to use just one function
import ast
table = open('file.txt').read()
mydict = ast.literal_eval(table)
random_value = choice(mydict.values())

Related

I need to pull the text of an image file name from an array but am only getting "pyimage#" or "tkinter.PhotoImage object at X" as replies

I'm trying to create an array with an assortment of different randomized image files in it to display on a set of buttons in Tkinter. When a given button is clicked I'd like to add the text of that file's name to a new array. Basically, when button with imageX is clicked add "imageX" to a new array.
Unfortunately, I always get a return that isn't the image's filename, or the variable that I've set to correspond to that image, but instead either:
"tkinter.PhotoImage object at X" (where is X is a location like "0x0000020FC894D2E0") if the command is populationbeta.append (population[0])
or
"pyimage#" (where # is an integer that seems to relate to the number of images in the source file), if I change the command to populationbeta.append (str(population[0]))
I feel like there should be a simple way of doing this and I've tried every work around I can think of but I'm not getting it to work. Any help would be very much appreciated! Thanks!
Here's a shortened/simplified version of the code in question:
master=tkinter.Tk()
master.title("Not working")
a1b1c1 = PhotoImage(file = r"C:/users/jdavis319/documents/bushesoflove/BoLdraw/a1b1c1.png")
a1b1c2 = PhotoImage(file = r"C:/users/jdavis319/documents/bushesoflove/BoLdraw/a1b1c2.png")
a1b1c3 = PhotoImage(file = r"C:/users/jdavis319/documents/bushesoflove/BoLdraw/a1b1c3.png")
a1b2c1 = PhotoImage(file = r"C:/users/jdavis319/documents/bushesoflove/BoLdraw/a1b2c1.png")
a1b2c2 = PhotoImage(file = r"C:/users/jdavis319/documents/bushesoflove/BoLdraw/a1b2c2.png")
population = [a1b1c1, a1b1c2, a1b1c3, a1b2c1, a1b2c2]
populationbeta = []
populationbeta.append(population[0])
print(populationbeta)
This gives the result: "[<tkinter.PhotoImage object at 0x000001A419D4F070>]"
This gives the result: "[<tkinter.PhotoImage object at 0x000001A419D4F070>]"
Correct. That shows that you have a list of PhotoImage objects. If you want the filenames you can use .cget('file') on the objects. cget is a common tkinter method for getting the value of a configured option.
filenames = [image.cget('filename') for image in population]
Or, if you don't want to use a list comprehension to create a list of filenames, you can do it on an individual image like so:
populationbeta.append(population[0].cget("file"))

CSV iterate/loop

I am trying to iterate through all the cells of a CSV row ( name, screen_name and image url). Different errors show up, I tried with pandas but still I am unable to finish the job. My CSV looks like this:
screen_name,name,image_url_https
Jan,Jan,https://twimg.com/sticky/default_profile_images/default_profile_normal.png
greg,Gregory Kara,https://twimg.com/profile_images/60709109/Ferran_Adria_normal.jpg
hillheadshow,Hillhead 2020,https://twimg.com/profile_images/1192061150915178496/cF6jOCRV_normal.jpg
hectaresbe,Hectaresbe,https://twimg.com/profile_images/1190957150996226048/lJnRnFwi_normal.jpg
Sdzz,Sanne,https://twimg.com/profile_images/1159005129879801856/8p6KC1ei_normal.jpg
and the part of the code that I need to change is:
import json
import time,os
import pandas as pd
screen_name = 'mylist'
file = pd.read_csv("news2.csv", header=0)
col = file.head(0)
columns = list(col)
fp=codecs.open(screen_name+'.csv','w',encoding="utf-8")
i=0
while True:
try:
i+=1
print (i)
name=['name']
uname=['screen_name']
urlimage=['image_url_https']
The values are ok with #Snake_py code, next i am doing a request:
myrequest='https://requesturl.com/'+uname
#print(myrequest)
resp=requests.get(myrequest)
I get the following error:
raise InvalidSchema("No connection adapters were found for '%s'" % url)requests.exceptions.InvalidSchema: No connection adapters were found for '0 https://requesturl.com/Jan
Name: name, dtype: object'
timeout error caught.
the easiest way to iterate through a csv with Python would be:
name = []
uname = []
urlimage =[]
open with ('url', 'r') as file:
for row in file:
row = row.strip().split(";")
name.append(row[0])
uname.append(row[1])
urlimage.append(row[2])
print(name)
print(uname)
print(urlimage)
First I created three empty arrays. then I open the file and iterate over each row in the file. Row will be returned as an array. So you can run the normal index command [] to get the needed part of the array to append it to the empty list.
For the method above you might run into an encoding problem, so I would recommend method 2, although you actually do not iterate over the rows then.
Alternatively you could just do:
import pandas as pd
file = pd.read_csv("news2.csv", header=0)
name = file['name']
uname = file['uname']
urlimage = file['urlimage']
For the second method, you need to make sure that your header has the correct spelling

JSON array keyerror in Python

I'm fairly new to Python programming and am attempting to extract data from a JSON array. Below code results in an error for
js[jstring][jkeys]['5. volume'])
Any help would be much appreciated.
import urllib.request, urllib.parse, urllib.error
import json
def DailyData(symb):
url = https://www.alphavantage.co/queryfunction=TIME_SERIES_DAILY&symbol=MSFT&apikey=demo
stockdata = urllib.request.urlopen(url)
data = stockdata.read().decode()
try:
js = json.loads(data)
except:
js = None
jstring = 'Time Series (Daily)'
for entry in js:
i = js[jstring].keys()
for jkeys in i:
return (jkeys,
js[jstring][jkeys]['1. open'],
js[jstring][jkeys]['2. high'],
js[jstring][jkeys]['3. low'],
js[jstring][jkeys]['4. close'],
js[jstring][jkeys]['5. volume'])
print('volume',DailyData(symbol)[5])
Looks like the reason for the error is because the returned data from the URL is a bit more hierarchical than you may realize. To see that, print out js (I recommend using a jupyter notebook):
import urllib.request, urllib.parse, urllib.error
import ssl
import json
import sqlite3
url = "https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=MSFT&apikey=demo"
stockdata = urllib.request.urlopen(url)
data = stockdata.read().decode()
js = json.loads(data)
js
You can see that js (now a python dict) has a "Meta Data" key before the actual time series begins. You need to start operating on the dict at that key.
Having said that, to get the data into a table like structure (for plotting, time series analysis, etc), you can use pandas package to read the dict key directly into a dataframe. The pandas DataFrame constructor accepts a dict as input. In this case, the data was transposed, so the T at the end rotates it (try with and without the T and you will see it.
import pandas as pd
df=pd.DataFrame(js['Time Series (Daily)']).T
df
Added edit... You could get the data into a dataframe with a single line of code:
import requests
import pandas as pd
url = "https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=MSFT&apikey=demo"
data = pd.DataFrame(requests.get(url).json()['Time Series (Daily)']).T
DataFrame: The contructor from Pandas to make data into a table like structure
requests.get(): method from the requests library to fetch data..
.json(): directly converts from JSON to a dict
['Time Series (Daily)']: pulls out the key from the dict that is the time series
.T: transposes the rows and columns.
Good luck!
Following code worked for me
import urllib.request, urllib.parse, urllib.error
import json
def DailyData(symb):
# Your code was missing the ? after query
url = "https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol={}&apikey=demo".format(symb)
stockdata = urllib.request.urlopen(url)
data = stockdata.read().decode()
js = json.loads(data)
jstring = 'Time Series (Daily)'
for entry in js:
i = js[jstring].keys()
for jkeys in i:
return (jkeys,
js[jstring][jkeys]['1. open'],
js[jstring][jkeys]['2. high'],
js[jstring][jkeys]['3. low'],
js[jstring][jkeys]['4. close'],
js[jstring][jkeys]['5. volume'])
# query multiple times, just to print one item?
print('open',DailyData('MSFT')[1])
print('high',DailyData('MSFT')[2])
print('low',DailyData('MSFT')[3])
print('close',DailyData('MSFT')[4])
print('volume',DailyData('MSFT')[5])
Output:
open 99.8850
high 101.4300
low 99.6700
close 101.1600
volume 19234627
Without seeing the error, it's hard to know what exact problem you were having.

Transfer Property ids (Array) to other TestCases in SoapUI/Groovy

I have an API to get list of ids, name, data etc. (TestCase name GET-APIs_OrderdByID_ASC)
I want to transfer those IDs to other following TestCases in same TestSuite or other TestSuite.
In SOAPUI, Property Transfer works within TestSteps in same TestCase. (Using OpenSource version). I need to transfer the property value among different TestCases / TestSuites.
Below is the code that I can extract ids from one testCase and also name of testCases/testSteps where I want to transfer.
import com.eviware.soapui.impl.wsdl.teststeps.*
import com.eviware.soapui.support.types.StringToStringMap
import groovy.json.*
def project = context.testCase.testSuite.project
def TestSuite = project.getTestSuiteByName("APIs")
def TestCase = TestSuite.getTestCaseList()
def TestStep = TestCase.testStepList
def request = testRunner.testCase.getTestStepByName("List_of_APIs_OrderByID_ASC")
def response = request.getPropertyValue("Response")
def JsonSlurperResponse = new JsonSlurper().parseText(response)
def Steps = TestStep.drop(3)
log.info JsonSlurperResponse.data.id
def id = JsonSlurperResponse.data.id
Steps.each {
it.getAt(0).setPropertyValue("apiId", id.toString())
log.info it.getAt(0).name
}
If I run above code, all the array values of id [1, 2, 10, 11, 12, 13, 14, 15, 16, 17, 18] are set to each of the following testSteps
I looked some other SO questions
Property transfer in SOAPUI using groovy script
groovy-script-and-property-transfer-in-soapui
Can anyone help me out. :-)
I have done something with datasinks as Leminou suggests.
Datasinks are a good solution for this. In test A, create a datasink step to persist the values of interest. Then in the target step, use a data source step, which links to the file generated by the datasink earlier.
The data sink can be configured to append after each test or start afresh.
If you're struggling to tease out the values for the datasink, create a groovy step that returns the single value you want, then in the datasink step, invoke the groovy.
Sounds a little convoluted, but it works.
You can use project level properties or testSuiteLevel properties or testCase Properties.
This way you can achieve the same thing that you get from Property Transfer step but in a different way.
Write a groovy step in the source test case to setProperty(save values you want to use later)
testRunner.testCase.setPropertyValue("TCaseProp", "TestCase")
testRunner.testCase.testSuite.setPropertyValue("TSuiteProp","TestSuite")
testRunner.testCase.testSuite.project.setPropertyValue("ProjectLevel","ProjectLevelProperty")
"TCaseProp" is the name of the property. you can give any name
"TestCase" is the value you want to store. You can extract this value and use a variable
for example
def val="9000"
testRunner.testCase.setPropertyValue("TCaseProp", val)
You can use that property in other case of same suite. If you want to use across different suites you can define project level property
use the below syntax in target testcase request
${#Project#ProjectLevel}
${#TestCase#TCaseProp}
${#TestSuite#TCaseProp}
<convertCurrency>${#TestSuite#TCaseProp}</ssp:SystemUsername>
System will automatically replace the property value in above request
https://www.soapui.org/scripting-properties/tips-tricks.html <-- Helpful link which can explain in detail about property transfer
Well the following Script works.
Just to change as
Steps.each { s ->
id.each { i ->
s.getAt(0).setPropertyValue("apiId", i.toString())
}
}
Here id is a ArrayList type. So We can loop through the List.
PS: We can do the same using for loop.

Python: Can you extend an array on each iteration using glob (or similar) to read in files from a directory

Is there a way to extend an array that stores data from a file on each iteration of a for-loop and with command combo, using glob. Currently, I have something like
import glob
from myfnc import func
for filename in glob.glob('*.dta'):
with open(filename,'rb') as thefile:
fileHead, data = func(thefile)
where func is defined in another script myfnc. What this does is on each iteration in the directory, stores the data from each file in fileHead and data (as arrays), erasing whatever was there on the previous iteration. What I need is something that will extend each array on each pass. Is there a nice way to do this? It doesn't need to be a for-loop, with combo. That is just how I am reading in all files from the directory.
I thought of initializing the arrays beforehand and then try extending them after the with is done on one pass, but it was giving me some kind of error with the extend command. With the error, the code would look like
import glob
from myfnc import func
fileHead, data = [0]*2
for filename in glob.glob('*.dta'):
with open(filename,'rb') as thefile:
fileHeadExtend, dataExtend = func(thefile)
fileHead.extend(fileHeadExtend)
data.extend(dataExtend)
So, the issue that it has is fileHead and data are both initialized but as int's. However, I don't want want to initialize the arrays to so many zeros. There should not be any arbitrary values in there to begin with. So, that is where issue is lying for this.
You want:
import glob
from myfnc import func
fileHead = list()
data = list()
for filename in glob.glob('*.dta'):
with open(filename,'rb') as thefile:
fileHeadExtend, dataExtend = func(thefile)
fileHead.extend(fileHeadExtend)
data.extend(dataExtend)

Resources