I have a Python script that does some complicated statistical calculations on data and want to sell it. I thought about compiling it, but I have read that Python compiled with py2exe can be easily decompiled. So I tried another aproach, namely running the script from the Internet.
Now my code, in file local.py looks like:
local.py
#imports
#define variables and arrays
#very complicated code i want to protect
I want to obtain something like:
File local.py:
#imports
#define variables and arrays
#call to online.py
print(result)
File online.py:
#code protected
#exit(result)
Is there is a better way to do this ?
I want client to run the code without being able to see it.
A web API would work great for this, which is a super simple thing to do. There are numerous Python frameworks for creating simple HTTP APIs, and even writing one from scratch with just low level sockets wouldn't be too hard. If you only want to protect the code itself, you don't even need security features.
If you only want people who've paid for the usage to have access to your API, then you'll need some sort of authentication, like an API key. That's a pretty easy thing to do too, and may come nearly for free from some of the aforementioned frameworks.
So your client's code might look something like this:
File local.py:
import requests
inputdata = get_data_to_operate_on()
r = requests.post('https://api.gustavo.com/somemagicfunction?apikey=23423h234h2g432j34', data=inputdata)
if r.status_code == 200:
result = r.json()
# operate on the resulting JSON here
...
This code does a HTTP POST request, passing whatever data is returned by the get_data_to_operate_on() call in the body of the request. The body of the response is the result of the processing, which in this code is assumed to be JSON data, but could be in some other format as well.
There are all sorts of options you could add, by changing the path of the request (the '/somemagicfunction' part) or by adding additional query parameters.
This might help you to get started on the server side: https://nordicapis.com/8-open-source-frameworks-for-building-apis-in-python. And here's one way to host your Python server code: https://devcenter.heroku.com/articles/getting-started-with-python
Related
Given an existing report on SalesForce that I created, can I update the content of the report using simple_salesforce package in python?
# A Pseudo code to get the expected result
from simple_salesforce import Salesforce
sf = Salesforce(username='my_user_name',
password='my_password',
security_token='my_security_token')
export_url = "link to the report I want to change"
session = requests.Session()
response = requests.get(export_url,
headers=sf.headers,
cookies={'sid': sf.session_id})
# this part is pseudo-code, for instance, I want to change a column of the report, I change it and then upload the new version as the current report
response.update(response, data)
You're bit out of Simple's comfort zone. You don't manipulate data, you don't even use restful call for "normal" API operations. You just (ab)use simple's login functionality to get the session id and pretend you're a browser. So you can experiment with requests below in Postman for example and then go back to your Python program.
I wonder if you're overcomplicating it. Are you sure you absolutely need a report?
Maybe it can be done with a normal SOQL query?
There's proper API for reports and a way to filter a report on the fly. It won't save the changes to the report. But that API will return results as JSON, you probably coded your stuff around CSVs.
If you need to actually save changes - there are proper Tooling API/Metadata API calls to fetch, modify and deploy back the report definition as XML file. Again - simple might not be best tool for the task, sfdx might fare better.
I suspect you'll ignore all these and stick to faking a browser. Google around for "url hacking", for example here. As it becomes more config than code issue - you can find some good stuff in dedicated sister site that has more admins than stackoverflow. For example https://salesforce.stackexchange.com/q/110219/799
For a webapp project I'm making multiple api calls. Each is a long link so my file is looking pretty cluttered.
I tried making a seperate file in which I can store my api calls, but the problem I then encountered was that the api calls get made when the file is loaded. This is obviously something I don't want.
What I think will work is making a function for each api call and store these functions in the other file, but to me this seems a bit overkill and not very beautiful.
Is there some better way I don't know about?
Edit: I can't just save the string, because the api is id dependent.
sample api call:
video = requests.get(f'https://api.themoviedb.org/3/movie/{id}/videos?api_key=e7319c984bf89b3efa98e5a0106691b7&language=en-US')
I am using suds to request data from a 3rd party using a wsdl. I am only saving some of the data returned for now, but I am paying for the data that I get so I would like to keep all of it. I have decided that the best way to save this data is by capturing the raw xml response into a database field both for future use should I decide that I want to start using different parts of the data and as a paper trail in the event of discrepancies.
So I have a two part question:
Is there a simple way to output the raw received xml from the suds.client object? In my searches for the answer to this I have learned this can be done through logging, but I was hoping to not have to dig that information back out of the logs to put into the database field. I have also looked into the MessagePlugin.recieved() hook, but could not really figure out how to access this information after it has been parsed, only that I can override that function and have access to the raw xml as it is being parsed (which is before I have decided whether or not it is actually worth saving yet or not). I have also explored the retxml option but I would like to use the parsed version as well and making two separate calls, one as retxml and the other parsed will cost me twice. I was hoping for a simple function built into the suds client (like response.as_xml() or something equally simple) but have not found anything like that yet. The option bubbling around in my head might be to extend the client object using the .received() plugin hook that saves the xml as an object parameter before it is parsed, to be referenced later... but the execution of such seems a little tricky to me right now, and I have a hard time believing that the suds client doesn't just have this built in somewhere already, so I thought I would ask first.
The other part to my question is: What type of django model field would be best suited to handle up to ~100 kb of text data as raw xml? I was going to simply use a simple CharField with a stupidly long max_length, but that feels wrong.
Thanks in advance.
I solved this by using the flag retxml on client initialization:
client = Client(settings.WSDL_ADDRESS, retxml=True)
raw_reply = client.service.PersonSearch(soapified_search_object)
I was then able to save raw_reply as the raw xml into a django models.TextField()
and then inject the raw xml to get a suds parsed result without having to re-submit my search lika so:
parsed_result = client.service.PersonSearch(__inject={'reply': raw_reply})
I suppose if I had wanted to strip off the suds envelope stuff from raw reply I could have used a python xml library for further usage of the reply, but as my existing code was already taking the information I wanted from the suds client result I just used that.
Hope this helps someone else.
I have used kyrayzk solution for a while, but have always found it a bit hackish, as I had to create a separate dummy client just for when I needed to process the raw XML.
So I sort of reimplemented .last_received() and .last_sent() methods (which were (IMHO, mistakenly) removed in suds-jurko 0.4.1) through a MessagePlugin.
Hope it helps someone:
class MyPlugin(MessagePlugin):
def __init__(self):
self.last_sent_raw = None
self.last_received_raw = None
def sending(self, context):
self.last_sent_raw = str(context.envelope)
def received(self, context):
self.last_received_raw = str(context.reply)
Usage:
plugin = MyPlugin()
client = Client(TRTH_WSDL_URL, plugins=[plugin])
client.service.SendSomeRequest()
print plugin.last_sent_raw
print plugin.last_received_raw
And as an extra, if you want a nicely indented XML, try this:
from lxml import etree
def xmlpprint(xml):
return etree.tostring(etree.fromstring(xml), pretty_print=True)
I am learning python. I have created some scripts that I use to parse various websites that I run daily (as their stats are updated), and look at the output in the Python interpreter. I would like to create a website to display the results. What I want to do is run my script when I go to the site, and display a sortable table of the results.
I have looked at Django and am part way through the tutorial, but it seems like an awful lot of overhead for what should be a simple problem. I know that I could just write a Python script to output simple HTML, but is that really the best way? I would like to be able to sort the table by various columns.
I have years of programming experience (C, Java, etc.), but have very little web development experience.
Thanks in advance.
Have you considered Flask? Like Tornado, it is both a "micro-framework" and a simple web server, so it has everything you need right out of the box. http://flask.pocoo.org/
This example (right off the homepage) pretty much sums up how simple the code can be:
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run()
If you are creating non-interactive pages, you can easily setup any modern web server to execute your python script as a CGI. Instead of loading a static file, your web server will return the output of your python script.
This isn't very sophisticated, but if you are simply returning the output without needing browser submitted date, this is the easiest way (scaling under load is a different story).
You don't even need the "cgi" module from python, if you aren't receiving any data from the browser. Anything more complicated than this and you should use a web framework.
Examples and other methods
Simple Example: hardest part is webserver configuration
mod_python: Cut down on CGI overhead (otherwise, apache execs the python interpreter for each hit)
python module cgi: sending data to your python script from the browser.
Sorting
Javascript side sorting: I've used this javascript library to add sortable tables. This is the easiest way to add sorting without requiring additional work or another HTTP GET.
Instructions:
Download this file
Add to your HTML
Add class="sortable" to any table you'd like to make sortable
Click on the headers to sort
You might consider Tornado if Django is too much overhead. I've used both and agree that, if you have something simple/small to do and don't already know Django, it's going to exponentially increase your time to production. On the other hand, you can 'get' Tornado in a couple of hours and get something relatively simple done in a day or two with no prior experience with it. At least, that's been my experience with it.
Note that Tornado is still a tradeoff: you get a lot of simplicity in exchange for the huge cornucopia of features and shortcuts you get w/ Django.
PS - in addition to being a 'micro-framework', Tornado is also its own web server, so there's no mucking with wsgi/mod-cgi/fcgi.... just write your request handlers and run it. Be sure to see the demos included in the distribution.
Have you seen bottle framework? It is a micro framework and very simple.
If I correctly understood your requirements you might find Wooey very interesting.
Wooey is a A Django app that creates automatic web UIs for Python scripts:
http://wooey.readthedocs.org
Here you can check a demo:
https://wooey.herokuapp.com/
Django is a big webframework, meant to include loads of things becaus eyou often needs them, even though sometimes you don't.
Look at Pyramid, earlier known as BFG. It's much smaller.
http://pypi.python.org/pypi/pyramid/1.0a1
Other microframeworks to check out are here: http://wiki.python.org/moin/WebFrameworks
On the other hand, in this case it's probably also overkill. sounds like you can run the script once every ten minites, and write a static HTML file, and just use Apache.
If you are not willing to write your own tool, there is a pretty advanced tool for executing your scripts: http://rundeck.org/
It's pretty simple to start and can be configured for complex scenarios as well.
For the requirement of custom view (with sortable results), I believe you can implement a simple plugin for translating script output into html elements.
Also, for simple setups I could recommend my own tool: https://github.com/bugy/script-server. It doesn't have tons of features, but very easy for end-users and supports interactive execution.
If you don't need any input from the browser, this sounds like an almost-static webpage that just happens to change once a day. You'll only need some way to get html out of your script, in a place where your webserver can access it.)
So you'd use some form of templating; if you'll need some structure above the single page, there's static site / blog generators that you can feed your output in, say, Markdown format, and call their make html or the like.
You can use DicksonUI https://dicksonui.gitbook.io
DicksonUI is better
Or Remi gui(search in google)
DicksonUI is better.
I am the author of DicksonUI
So ive just started learning python on WAMP, ive got the results of a html form using cgi, and successfully performed a database search with mysqldb. I can return the results to a page that ends with .py by using print statements in the python cgi code, but i want to create a webpage that's .html and have that returned to the user, and/or keep them on the same webaddress when the database search results return.
thanks
paul
edit: to clarify on my local machine, i see /localhost/search.html in the address bar i submit the html form, and receive a results page at /localhost/cgi-bin/searchresults.py. i want to see the results on /localhost/results.html or /localhost/search.html. if this was on a public server im ASSUMING it would return .../cgi-bin/searchresults.py, the last time i saw /cgi-bin/ directories was in the 90s in a url. ive glanced at addhandler, as david suggested, im not sure if thats what i want.
edit: thanks all of you for your input, yep without using frameworks, mod_rewrite seems the way to go, but having looked at that, I decided to save myself the trouble and go with django with mod_wsgi, mainly because of the size of its userbase and amount of docs. i might switch to a lighter/more customisable framework, once ive got the basics
First, I'd suggest that you remember that URLs are URLs and that file extensions don't matter, and that you should just leave it.
If that isn't enough, then remember that URLs are URLs and that file extensions don't matter — and configure Apache to use a different rule to determine that is a CGI program rather than a static file to be served up as is. You can use AddHandler to add a handler for files on the hard disk with a .html extension.
Alternatively, you could use mod_rewrite to tell Apache that …/foo.html means …/foo.py
Finally, I'd suggest that if you do muck around with what URLs look like, that you remove any sign of something that looks like a file extension (so that …/foo is requested rather then …/foo.anything).
As for keeping the user on the same address for results as for the request … that is just a matter of having the program output the basic page without results if it doesn't get the query string parameters that indicate a search term had been passed.