Wednesday, 29 November 2017

Installing MySQL and SQLite on Windows 10

MySQL is a free version of SQL, the most commonly used database system on the web.
Downloading it from https://dev.mysql.com/downloads/installer/ , going for the web community installation, developer set-up.
Also ended up installing Microsoft Visual C++
Ran into problems where it expected Python 3.4 to be installed, and did not recognise Python 3.6
Installed Python 3.4 from an old download on another computer
On the Python website, 3.4 was as a GZIP, with the script needed to install Python 3.4 as a .sln file which had to be run by MS Visual C++/Studio. I knew this was installed, but I couldn't work out how to open the file using MS Visual C++ - at this point I decided it wasn't worth it.
Setting up this stuff can be painful.
After staring blankly at MySQL workbench, I went back to Google and checked out alternatives to MySQL. Settled on SQLite3.

Downloaded SQLite from https://sqlite.org/download.html
There is no actual installation - simply placing the downloaded files in a suitable folder on your drive - not C:\Program Files - I found that you need to run Python as Administrator to create in/write to folders in Program Files, and I can't be bothered with that.
So now the files are sitting in C:\sqlite\, with an extra folder at C:\sqlite\db\ and it seems okay.
The module you need to import into Python scripts is sqlite3, which is already built into recent Python versions.
I actually got a lot of help from http://www.sqlitetutorial.net/download-install-sqlite/
Although it talks about getting the GUI version, at the moment I will stick with the command-line version just to keep it as simple as possible.
There was also a first Python script to connect to a database, creating one if it doesn't already exist. I modified only the path to find the db file.
import sqlite3
from sqlite3 import Error


def create_connection(db_file):
    """ create a database connection to a SQLite database """
    try:
        conn = sqlite3.connect(db_file)
        print(sqlite3.version)
        conn.close()
    except Error as e:
        print(e)

if __name__ == '__main__':
    create_connection('C:\\sqlite\\db\\base1.db')

And it seems to work as intended (once I got the path right...).
On the Python command line I get
========= RESTART: C:\Users\pc\Documents\Programming\sqlitetest2.py =========
2.6.0
>>>


while in the relevant folder a new file base1.db has just appeared.


Tuesday, 28 November 2017

After a long break, a binary converter

Despite the lack of activity, I haven't completely given up on this blog. Things are getting busier with Open University modules, so more of my mental energy has gone into academic study rather than self-motivated learning about Python.

However, I have come up with something short and sweet. This is something of a step away from some of the more challenging topics I was considering. Classes, objects, regular expressions and SQLite are subjects I am intending to get onto, but currently I am not really confident about posting stuff that I have only just got my head around.

So here I present a program that convert numbers from decimal to binary:
#!/usr/bin/python3

print ("Binary Converter Program")
num = input("Please enter decimal number to be converted: ")
num = int(num)

comparator = 1
digcount = 0
while comparator <= num:
    digcount += 1
    comparator *= 2

print ('Number of digits is', digcount)
print ('Chosen number is less than', comparator)

binstring = ''
while digcount > 0:
    digcount -= 1
    comparator = 2** digcount
    if num - comparator >= 0:
        binstring = binstring + '1'
        num = num - comparator
    else:
        binstring = binstring + '0'
    
if binstring == '':
    binstring = '0'
print ('Binary string is', binstring)
This gives the outputs:
>>>
RESTART: C:\Users\666\Dropbox\Misc Programming\Python\python3\binaryconverter.py
Binary Converter Program
Please enter decimal number to be converted:
19
Number of digits is 5
Chosen number is less than 32
Binary string is 10011

>>>
RESTART: C:\Users\666\Dropbox\Misc Programming\Python\python3\binaryconverter.py
Binary Converter Program
Please enter decimal number to be converted:
187
Number of digits is 8
Chosen number is less than 256
Binary string is 10111011

>>>
RESTART: C:\Users\666\Dropbox\Misc Programming\Python\python3\binaryconverter.py
Binary Converter Program
Please enter decimal number to be converted:
2017
Number of digits is 11
Chosen number is less than 2048
Binary string is 11111100001
>>> 
I admit the  printout of "number of digits" and "chosen number is less than" is diagnostic, and probably not useful for any user.
Similarly, I am not sure if this is the simplest, most elegant or most Pythonic way of doing this task, but  it seems to work so that's good enough for me. If there is a better way, feel free to let me know.
A few notes about how I have done this:

  • The digcount variable is first used to record how many binary digits the converted number will have. It is then used to keep track of which column / digit in the binary printout is being tested to see if it should be a '1' or '0'. 
  • The comparator variable also serves a dual purpose. Firstly to see if the number being converted is bigger or smaller than a power of 2 (i.e. 2 ** x). Secondly while the number is reduced by having powers of 2 subtracted from it, the comparator is used to see if that gives a '1' or a '0' for that digit/power of 2. 
  • There is a lot of use of the +=, -+ and *= operators, to change a variable by a certain amount. 
  • Finally the outputted binary 'number' is actually a string. It just seemed more convenient that way.  


Wednesday, 25 October 2017

Prime Numbers and Goldbach's Conjecture with Python

Prime numbers (those integers that cannot be divided neatly without fractions or remainders by any other numbers except 1 and itself) are big business. As in they are used in business mainly for secure transactions. Other folks just find them interesting in their own right, speculating whether they follow a predictable pattern (which we have not discovered yet) or not.

The method I have written for finding them is not nearly as sophisticated as those of more skilled mathematicians. It uses a method called the Sieve of Eratosthenes. Basically the program takes a number and tries to divide it by all the numbers below it (except for 1). If any do divide neatly, then it is not a prime number.

Another mathematician called Goldbach came up with a conjecture that any non-prime number could be created by adding two prime numbers together. So for example, 2 is a prime, 4 is not a prime and can be expressed as 2 * 2, or in Goldbach's conjecture 2+2.
Goldbach's conjecture seems to hold true as far as practical calculations show, but nobody is sure if that is because of some important underlying principle or if it is just very easy to do so.

So this program asks for a maximum number. It then goes from 2 to the maximum number, using the sieve of Eratosthenes to find if each number is a prime, and if not then whether it fits Goldbach's conjecture.


#!/usr/bin/python3
def goldbach(evennumber):
    for x in primelist:
        for y in primelist:
            if x + y == evennumber:
                print(", Goldbach conjecture: "+str(x)+" + "+str(y)+" = "+str(evennumber))
                return()
    print("Problem with Goldbach Conjecture!"); exit()
count = 0
maxcount = input("Please enter maximum count: ")
try: int(maxcount)
except: print("Bad input"); exit()
else: maxcount = int(maxcount)
testnumber = 2
primelist = [2]
while count < maxcount-2 :
    testnumber +=1
    prime = True
    count += 1
    for testfactor in primelist:
        if testnumber % testfactor == 0:
            print(str(testnumber)+" is divisible by "+str(testfactor), end='')
            prime = False
            if testfactor == 2: goldbach(testnumber)
            else: print('')
            break
    if prime == True:
        primelist.append(testnumber)
        print(str(testnumber) + " is a prime!")
#print(primelist)
print("Length of prime list is "+str(len(primelist)))
And a typical output is:

>>> ================================ RESTART ================================
>>>
Please enter maximum count: 2000
3 is a prime!
4 is divisible by 2, Goldbach conjecture: 2 + 2 = 4
5 is a prime!
6 is divisible by 2, Goldbach conjecture: 3 + 3 = 6
7 is a prime!
.....
1996 is divisible by 2, Goldbach conjecture: 3 + 1993 = 1996
1997 is a prime!
1998 is divisible by 2, Goldbach conjecture: 5 + 1993 = 1998
1999 is a prime!
2000 is divisible by 2, Goldbach conjecture: 3 + 1997 = 2000
Length of prime list is 303

>>>


 

Monday, 23 October 2017

Gravity and Radius for a Stanford Torus

In science fiction one way to get around the lack of gravity is to produce artificial gravity by centrifugal force - spinning something around in a circle will create an acceleration similar to gravity as it tries to travel in a straight line and therefore away from the centre of rotation.

The rotating space station has become a staple of science fiction, most notably in Stanley Kubrik's 2001: A Space Odyssey, and in Elysium. It was first seriously proposed at Stanford University and has since become known as the Stanford Torus.
One thing I wondered is how big does a space station need to be to produce Earth-like gravity (9.8 m/s2)? It actually depends on how fast it is rotating.
I had a look online and found the equation I was looking for:
Acceleration = velocity2 / radius

So I came up with a Python program to help work it out. Given any two factors in that equation the program will calculate the third plus the period of rotation (how long it takes to make a complete rotation).
#!/usr/bin/python3
import math
print ("Program for calculating stats of Stanford Torus")
rad = input("Please enter radius (m): ")
if rad == "": radGiven = False
elif int(rad) > 0:
    radGiven = True
    rad = float(rad)
    circumf = 2 * math.pi * rad
else: print ("Invalid answer"); radGiven = False
accel = input("Please enter required centripetal acceleration (m/s2): ")
if accel == "": accelGiven = False
elif float(accel) > 0: accelGiven = True; accel = float(accel)
else: print ("Invalid answer"); accelGiven = False
if accelGiven == True and radGiven == True:
    veloc = math.sqrt(accel * rad)
    period = circumf / veloc
    print ("Velocity at edge is " + str(veloc) + "m/s")
    print ("Period at edge is " + str(period) +"sec")
else:
    period = input("Please enter period in sec: ")
    if period == "": print("Not enough information for calculation")
    elif float(period) > 0 and radGiven == True:
        period = float(period)
        veloc = circumf / period
        print ("Velocity at edge is " +str(veloc) + "m/s")
        accel = veloc * veloc / rad
        print("Acceleration at edge is " + str(accel) + "m/s2")
    elif float(period) > 0 and accelGiven == True:
        period = float(period)
        veloc = period * accel
        rad = veloc * veloc / accel
        print ("Velocity at edge is " + str(veloc) + "m/s")
        print ("Radius at edge is " + str(rad) + "m")

And here are some typical results.
======== RESTART: C:\Users\pc\Documents\Programming\StanfordTorus.py ========
Program for calculating stats of Stanford Torus
Please enter radius (m):
200
Please enter required centripetal acceleration (m/s2):
Please enter period in sec:
200
Velocity at edge is 6.283185307179586m/s
Acceleration at edge is 0.19739208802178715m/s2

>>>
======== RESTART: C:\Users\pc\Documents\Programming\StanfordTorus.py ========
Program for calculating stats of Stanford Torus
Please enter radius (m):
Please enter required centripetal acceleration (m/s2):
4.9
Please enter period in sec: 20
Velocity at edge is 98.0m/s
Radius at edge is 1959.9999999999998m

>>>
As you can see, entering a blank into the input for one of the factors will mean the program will try to calculate that missing factor.
Importing the math module gives us a quick and accurate value of Pi, necessary for the velocity at the edge of the torus.

Thursday, 19 October 2017

A script to convert CSV to HTML tables

HTML can be a pain to write manually, especially when it comes to tables.
This script does the basics. It asks for and tries to open up the source file, then you give it the name of the new file the HTML table will be saved to.
It works on the very simple idea of splitting each row by its separator (which the user needs to specify, such as ; or ,) and then inserting the HTML 'separators' of <td> and </td>. It could be improved on - at the moment HTML/CSS formatting and style needs to be entered manually after conversion and there is no allowance for the first row being different. Nonetheless, I believe it could save me a lot of time and bother.
#!/usr/bin/python3
import sys

print ("HTML Table Maker!")
filechoice = input("Please enter name of file with data, including file extension: ")
try:
    FX= open(filechoice, 'r')
except:
    print("Invalid File Name!")
    exit()

print(FX.readline())
FX.seek(0) # Returns reading point back to top of file
sep = input("Please enter column separator: ")

newfile = input("New File name (inc. extension)? ")
FN = open(newfile, 'w')
FN.write('<table>\n')
for line in FX:
    linelist = line.split(sep)
    FN.write('\t<tr>')
    for col in linelist:
        FN.write('<td>'+col+'</td>')
    FN.write('</tr>\n')
FN.write('</table>\n')    
FX.close()
FN.close()

The line FX.seek(0) is a new thing - I may have mentioned before that when a Python program is writing to or reading from a file, it maintains a progress point, like a theoretical cursor. 
fileobject.seek(linenumber) resets this progress point to a particular line (in this case back to the start). 
And the output is as follows:
>>> ================================ RESTART ================================
>>> 
HTML Table Maker!
Please enter name of file with data, including file extension: groceries.csv
Butter (250g), 1.50, 2, 

Please enter column separator: ,
New File name (inc. extension)? groceries.html
>>> 
And now I can embed the contents of groceries.html into this blog page which is based on HTML:

Item NamePrice per ItemNumber of Items
Butter (250g)1.502
Chocolate Biscuits (300g)1.502
Flour (1kg)0.503
Milk (1 pint)0.705
Pork Sausages (500g)4.501
Rice (1kg)1.701
Strawberry Jam (400g)2.001

or even add a bit of formatting:

Item NamePrice per ItemNumber of Items
Butter (250g)1.502
Chocolate Biscuits (300g)1.502
Flour (1kg)0.503
Milk (1 pint)0.705
Pork Sausages (500g)4.501
Rice (1kg)1.701
Strawberry Jam (400g)2.001

Wednesday, 18 October 2017

Motivation for and Usefulness of Computer Programs

Why write programs? Is it purely a hobby? Is it a series of boxes for us to tick for work or study? Is it to show how clever we are?
For myself one major attraction to programming is the ability to create electronic tools that help me do things with data. I like to think that the code is not an end in itself but the way we get the results we want - whether that is entertaining, interesting or useful for some further purpose.
There is an essay/paper on software development called the Cathedral and the Bazaar by Eric S Raymond (link here). Throughout it he highlights a series of principles and lessons which I have found useful guidance. The very first one is:
  1. Every good work of software starts by scratching a developer's personal itch.
Although not always true for my programs (some of them are about investigating a new part of Python I've discovered or been told about), it certainly fits quite a few of my programs. It reminds me of a description of computer programming as "constructive laziness", creating something so you don't have to do so much work - it will do the work for you.   
In my mind there are a series of levels of usefulness of computer programs:
  • Stuff you could do in your own head. Imagine the words "Hello World". Okay, so why do you need to print it out? Or what's 2+3? If you need pencil and paper (or a Python program) to work that one out, maybe Python programming isn't for you. 
  • Stuff you can do with paper and pencil. What's 32 * 23? A few folks may well do that in their heads, but I need to work it out on paper. The answer is 736 by the way. What about using the Caesar Cipher? If all the letters are shifted one place forward along the alphabet, what is "J MPWF QZUIPO" when it is decoded? This is where computer programs may not be essential but can speed up processes.
  • Stuff you can do on office software. Spreadsheets, word processors, simple databases, email-managing programs and web browsers are so ubiquitous in the modern world that they are the first stop when solving problems or working on tasks that are too hard for pencil and paper. For loops in Python can be represented in a series of cells on a spreadsheet that reference each other. Similarly, the CSV files I've read and manipulated using Python can be opened on most spreadsheet programs. Heck, I'm impressed with whoever creates these, and very grateful as well. Whether I use these commercial programs or create a solution with my own Python program is often a matter of motivation and time. If I'm enthusiastic and have time to spare, I will have a go on Python. If I am in a hurry, or maybe the task is beyond my programming skill (which is often the case), I'll just open up the spreadsheet or whatever. 
  • Stuff you can do if you really know office software. This is a sort of follow-on from the previous type, in that if you can create functions in spreadsheets, can skilfully manipulate tables in word processors, do form letters etc. then you don't really need to write a Python program to do those things. If you know your spreadsheets, you could probably get it to create a D&D treasure generator. But if you don't, then programming the solution in Python can seem a reasonable alternative.   
  • Stuff that requires specialised software. These tasks are not easily solved on OpenOffice, MS Office or whatever you prefer. The solution may be out there in the wider world, but finding a trustworthy source that does not charge too much money is necessary. If I can do it in Python, then the time and effort spent learning Python really starts to pay off. Of course, that's a big if. 
  • Stuff where nobody else has created a software solution yet, and you can't do it in your head or on pencil and paper. This is where if you really want a software solution, you have to create it yourself (or maybe hire somebody else to write it for you, but then why are you reading this blog?). If you are not the only person to face this task, but you are the first one to solve it then you can make money from it. All commercial programs rely on supply and demand. If you are the only one supplying and there is enough demand, you could sell your work for a tidy sum - just look at the apps being created for smartphones. 
So is this the only reason why I do Python programming?
No. Actually, some of the reasons I offered at the top of this post are still valid. Programming is a creative process and can be quite satisfying. It stretches my mind and challenges me to do better. And it looks good on a CV as well.

Tuesday, 17 October 2017

Treasure Generator for Dungeons & Dragons

One of my hobbies has been Dungeons and Dragons. Although I don't play much these days, it has had a second lease of life as a subject to write computer programs for. Here is one such, when I was wondering how to generate a treasure hoard, given an approximate value and whether or not the treasure was mostly low-value copper coins, or high value gems and magic items.

#!/usr/bin/python3.5
import random
print ("Treasure hoard generating program")
print ("=================================")

print ("Please enter approximate value of treasure hoard: ")
total_value = input("? ")
total_value = int(total_value) # approximate total value. It doesn't work out precisely.

print ("On a scale of 1-10 how skewed is it towards high value items?")
skew = input("1= mostly low value coins, 10 = mostly magic items: ")
skew = int(skew) -1
# for ratio tuples [0] is copper, [1] is silver, [2] is electrum, [3] is gold
# [4] is platinum, [5] is gems, [6] is jewelry, [7] is magic items
skew_ratio1 = (0.75, 0.95, 0.98, 0, 0, 1, 0, 0)
skew_ratio2 = (0.50, 0.85, 0.90, 0.95, 0, 0.98, 1, 0)
skew_ratio3 = (0.30, 0.60, 0.70, 0.80, 0.85, 0.90, 0.95, 1)
skew_ratio4 = (0.25, 0.50, 0.65, 0.80, 0.85, 0.90, 0.95, 1)
skew_ratio5 = (0.15, 0.30, 0.45, 0.60, 0.75, 0.83, 0.91, 1)
skew_ratio6 = (0.10, 0.20, 0.40, 0.60, 0.75, 0.90, 0.95, 1)
skew_ratio7 = (0.07, 0.14, 0.20, 0.50, 0.65, 0.80, 0.90, 1)
skew_ratio8 = (0.05, 0.10, 0.15, 0.35, 0.50, 0.65, 0.80, 1)
skew_ratio9 = (0.03, 0.07, 0.12, 0.30, 0.45, 0.60, 0.85, 1)
skew_ratio10 = (0.01, 0.02, 0.10, 0.20, 0.30, 0.50, 0.75, 1)
skew_ratio_tup = (skew_ratio1, skew_ratio2, skew_ratio3, skew_ratio4, skew_ratio5, skew_ratio6, skew_ratio7, skew_ratio8, skew_ratio9, skew_ratio10)

selected_skew_ratio = skew_ratio_tup[skew] # should select the right set of ratios
spent_value = 0
copper_value = 0
silver_value = 0
electrum_value = 0
gold_value = 0
platinum_value = 0
gem_value = 0
jewelry_value = 0
magic_item_value = 0

chunk_number = 0
while spent_value < total_value:
    chunk_value = total_value * random.random() * 0.1
    chunk_choice = random.random()
    category_num = 0
    chunk_done = False
    for category in selected_skew_ratio:
        if category > chunk_choice and chunk_done == False:
            spent_value = spent_value + chunk_value
            if category_num == 0:
                copper_value = (copper_value + chunk_value)
            elif category_num == 1:
                silver_value = (silver_value + chunk_value)
            elif category_num == 2:
                electrum_value = (electrum_value + chunk_value)
            elif category_num == 3:
                gold_value = (gold_value + chunk_value)
            elif category_num == 4:
                platinum_value = (platinum_value + chunk_value)
            elif category_num == 5:
                gem_value = (gem_value + chunk_value)
            elif category_num == 6:
                jewelry_value = (jewelry_value + chunk_value)
            else:
                magic_item_value = (magic_item_value + chunk_value)
            #print (category_num, chunk_value)
            chunk_done = True
        else:
            category_num = category_num +1
    chunk_number = chunk_number +1
print ("Coins")
print ("=====")
copper_coins = format(int(copper_value * 100), ',d')
print ("Copper value = ", copper_value, "\n\tCopper Coins = ", copper_coins)
silver_coins = format(int(silver_value * 10), ',d')
print ("Silver value = ", silver_value, "\n\tSilver Coins = ", silver_coins)
electrum_coins = format(int(electrum_value * 5), ',d')
print ("Electrum value = ", electrum_value, "\n\tElectrum Coins = ", electrum_coins)
print ("Gold value = ", gold_value, "\n\tGold coins = ", format(int(gold_value), ',d'))
platinum_coins = format(int(platinum_value / 5), ',d')
print ("Platinum value = ", platinum_value, "\n\tPlatinum coins = ", platinum_coins)
print ("Gem value = ", gem_value)
print ("Jewelry value = ", jewelry_value)
print ("Magic Item value =", magic_item_value)
print ("Total assigned value = ", spent_value)
print ('\n')

gemstash = [] # what the treasure hoard contains - starts empty
total_gemvalue = 0
if gem_value < 10 and gem_value > 0:
    gem_string = ["1 small pretty stone worth ", int(gem_value)]
    total_gemvalue = total_gemvalue + int(gem_value)
else:
    gem_string = ""
    handle = open('gemfile.txt', 'r')
    gemlist = [] # table for storing data about gems
    for line in handle:
        linelist = line.split(', ')
        gemlist.append(linelist)
    remaining_gemvalue = gem_value
    size_tuple = ((0.2, "very small "), (0.5, "small "), (0.5, "small "), (1, "medium "), (1, "medium "), (1, "medium "), (2, "large "), (5, "huge "))
    quality_tuple = ((0.2, "poor "), (0.5, "flawed "), (0.5, "flawed "), (1, "normal "), (1, "normal "), (1, "normal "), (2, "flawless "), (5, "perfect "))
    while remaining_gemvalue >= 10:
        potential_gem = [random.choice(quality_tuple), random.choice(size_tuple), random.choice(gemlist)]
        potential_value = float(potential_gem[0][0]) * float(potential_gem[1][0]) * float(potential_gem[2][1])
        if potential_value <= remaining_gemvalue:
            gem_descrip = potential_gem[0][1] + potential_gem[1][1] + potential_gem[2][0]
            gem_final = [int(potential_value), gem_descrip]
            gemstash.append(gem_final)
            remaining_gemvalue = remaining_gemvalue - potential_value
            total_gemvalue = total_gemvalue + potential_value
    handle.close()
gemstash.append(gem_string)
print ("Gems")
print ("====")
for gem in gemstash:
    print (gem)
print ("Gem value is ", total_gemvalue)
print ('\n')

jewelrystash = []
jewelrylist = []
total_jewelryvalue = 0
remaining_jewelryvalue = jewelry_value
handle = open('jewelryfile.txt', 'r')
for line in handle:
    linelist = line.split(', ')
    linelist[1] = int(linelist[1])
    jewelrylist.append(linelist)
jewelry_tuple = (("plain ", 1), ("engraved ", 2), ("ornate ", 5), ("bejeweled ", 10))
metal_tuple = (("copper ", 1), ("silver ", 10), ("electrum ", 50), ("gold ", 100), ("platinum ", 500), ("mithril ", 2000))
while remaining_jewelryvalue >= 10:
    potential_jewel = [random.choice(jewelry_tuple), random.choice(metal_tuple), random.choice(jewelrylist)]
    potential_jewel_description = potential_jewel[0][0] + potential_jewel[1][0] + potential_jewel[2][0]
    potential_jewel_value = potential_jewel[0][1] * potential_jewel[1][1] * int(potential_jewel[2][1])
    if remaining_jewelryvalue > potential_jewel_value:
        jewelrystash.append((potential_jewel_description, potential_jewel_value))
        remaining_jewelryvalue = remaining_jewelryvalue - potential_jewel_value
        total_jewelryvalue = total_jewelryvalue + potential_jewel_value

print ("Jewellery")
print ("=========")
for jewel in jewelrystash:
    print (jewel)
print ("Jewelry value is", total_jewelryvalue)
print ("\n")
handle.close()

itemstash = []
itemlist = [] # magic items and values are from DMG 3.0
total_itemvalue = 0
remaining_itemvalue = magic_item_value
handle = open('magicitemfile.txt', 'r')
for line in handle:
    linelist = line.split(', ')
    linelist[1] = int(linelist[1])
    itemlist.append(linelist)
while remaining_itemvalue >= 200:
    potential_item = random.choice(itemlist)
    if remaining_itemvalue >= potential_item[1]:
        itemstash.append(potential_item)
        remaining_itemvalue = remaining_itemvalue - potential_item[1]
        total_itemvalue = total_itemvalue + potential_item[1]
print ("Magic Items")
print ("===========")
for magicitem in itemstash:
    print (magicitem)
print ("Magic Item value is ", total_itemvalue)

total_treasurevalue = (int(copper_value)) + (int(silver_value)) + (int(electrum_value)) + int(gold_value) + int(platinum_value) + total_gemvalue + total_jewelryvalue + total_itemvalue
print ("total treasure value is", total_treasurevalue)


First of all, this is a big program. 
Secondly it uses a number of data files, namely magicitemfile.txt, jewelryfile.txt and gemfile.txt. These contain large amounts of data that did not seem suitable to have in the main code. 
Thirdly this is not entirely accurate in total value - it gives amounts about 10% either side of initial required value. 

It works by splitting the treasure up into randomly-sized chunks between 0% and 10% of the required value. 
That chunk is then randomly determined to be a particular treasure type (copper coins, silver coins, gems, jewellery etc). Rather than equal chances for each type, the chances are determined by looking up the skew_ratio which then gives the chances for each type. 
If the chunk is made of coins, then the number of coins is determined based on the value of the chunk. 
If the chunk is made of gems, jewellery or magic items, then random examples of those are generate. If their values are equal to or less than that of the chunk then the item is added and the value of the item deducted from the chunk. If there is enough value left over in the chunk, another example is generated until the remaining value of the chunk falls below a threshold.   
And the end result? Here is a typical run, generating a 100,000gp-value treasure trove

 RESTART: C:/Users/John/Dropbox/Misc Programming/Python/python3/test08a_treasure.py
Treasure hoard generating program
=================================
Please enter approximate value of treasure hoard:
?
100000
On a scale of 1-10 how skewed is it towards high value items?
1= mostly low value coins, 10 = mostly magic items:
5
Coins
=====
Copper value =  14977.991665483956
 Copper Coins =  1,497,799
Silver value =  15397.31065665539
 Silver Coins =  153,973
Electrum value =  18959.482408553344
 Electrum Coins =  94,797
Gold value =  2479.269646407558
 Gold coins =  2,479
Platinum value =  24353.349234787212
 Platinum coins =  4,870
Gem value =  1626.2385405454738
Jewelry value =  8493.713069086232
Magic Item value = 14708.117885848227
Total assigned value =  100995.4731073674


Gems
====
[30, 'poor small Aquamarine']
[100, 'poor huge Iolite']
[100, 'normal medium Amber']
[100, 'flawed very small Emerald']
[50, 'normal small Tourmaline']
[1000, 'flawless huge Carnelian']
[20, 'normal very small Peridot']
[30, 'normal medium Rose Quartz']
[7, 'flawed small Citrine']
[60, 'normal very small Garnet']
[120, 'flawless very small Pearl']

Gem value is  1617.5

Jewellery
=========
('ornate electrum vase', 7500)
('engraved silver fork', 100)
('plain copper spoon', 5)
('engraved copper torc', 100)
('ornate copper spurs', 50)
('plain copper crown', 100)
('plain silver spurs', 100)
('plain silver spurs', 100)
('plain silver necklace', 150)
('plain copper knife', 5)
('bejeweled copper pin', 50)
('plain copper dagger', 50)
('bejeweled copper fork', 50)
('plain copper chain', 20)
('ornate copper earring', 50)
('engraved copper nosering', 20)
('engraved copper headband', 40)
Jewelry value is 8490


Magic Items
===========
['Wand of Magic Missile', 750, 'DMG 3.0\n']
['Longsword +2', 8315, 'DMG 3.0\n']
['Scroll of 5th level cleric spell', 1125, 'DMG 3.0\n']
['Bolts +1 (50)', 2350, 'DMG 3.0\n']
['Scroll of 5th level wizard spell', 1125, 'DMG 3.0\n']
['Potion of Heroism', 900, 'DMG 3.0\n']
Magic Item value is  14565
total treasure value is 100837.5

>>>


The presentation could do with some cleaning up, but the idea is sound. And just in case you do play Dungeons & Dragons, the magicitemfile.txt derives its information from 3rd Edition Dungeon Master's Guide. If you prefer a different edition, feel free to generate your own magicitemfile.txt