




No publisher Linux Python Reinteract free software my projects' weblogs data manipulation health fitness 2017/03/09 23:33:00 GMT+0 News Item
Calculate your way into a great e-juice mix! The geekiest way to prepare your e-liquid.


Preparation and setup

You need to install three things on your computer:

  1. Python 2.7.
  2. Reinteract for Python 2.7.
  3. The SymPy library.


Now launch Reinteract from your computer's programs menu.



The program


# Calculate the ingredients for any e-liquid mixture.
# All computed figures in milliliters.
# mlmg() converts to permille.
# perc() converts to percent.
from sympy import Symbol as S
from sympy import Eq, Rational
from sympy.solvers import solve
def fix(eqs, **args):
    neqs = []
    for i, eq in enumerate(eqs):
        for k,v in args.items():
            eq = eq.subs(k, v)
    return neqs
# Let's define our equations.



Now hit Ctrl+Enter.


Result 1:
      zeronic_volume: 13.00 ml
       flavor_volume: 1.00 ml
      nicbase_volume: 6.00 ml



So what are we doing here?



Happy mixing!

No publisher vaping HOWTO Python math 2016/08/25 01:37:00 GMT+0 News Item
Missing core Python modules in your Plone buildout? Sometimes when you install Plone, the installer will not compile certain modules during the Python compilation stage, simply because the development packages are not available. Here's how to fix that.

The problem manifests itself with error tracebacks attempting to import certain Plone eggs that require core Python functionality, which may or may not be available on your system.  We'll use the quintessential bpython example:

bin/debugclient debug
2012-07-21 13:31:54 WARNING SecurityInfo Conflicting security declarations for "setText"
2012-07-21 13:31:54 WARNING SecurityInfo Class "ATTopic" had conflicting security declarations
2012-07-21 13:31:59 WARNING Init Class Products.Five.metaclass.RedirectsView has a security declaration for nonexistent method 'errors'
>>> import bpython
>>> bpython.embed(locals_=locals())
Traceback (most recent call last):
  File "", line 1, in 
  File "/home/rudd-o/tmp/localplone/plonedevelwithbpython/buildout-cache/eggs/bpython-0.11-py2.6.egg/bpython/", line 30, in embed
    from bpython.cli import main
    import curses
  File "/opt/plonezeo/Python-2.6/lib/python2.6/curses/", line 15, in 
    from _curses import *
ImportError: No module named _curses

In this example, Python is telling us that its built-in curses module is not really built -- only the Python wrappers are available.

Naturally, this renders the use of the (amazing) bpython module for Zope unusable.

How to fix it

I'm assuming that you don't want to redo everything on your Plone deployment.  So here's how you go about redoing this:

  1. Install the pertinent development packages you need to build the binary modules.  In this case, it would be ncurses-devel.
  2. Download the same Plone installer version that you used to deploy your Plone deployment.
  3. Uncompress the tarball, and change into the created directory.
  4. Run the installer (./ with the following parameters:
    ./ --target=/some/temporary/path/you/must/create none
  5. That's it.  You now have a new Python inside the path /some/temporary/path/you/must/create.  Next step is up.
  6. Synchronize your newly-created Python environment with the Plone development Python environment.
    rsync -av /some/temporary/path/you/must/create/Python*/ /path/to/your/plone/deployment/Python*/

Voilá.  You now have a Python inside your Plone deployment that has the requisite binary modules enabled.

No publisher bpython Python Zope tips Plone 2012/07/21 20:55:00 GMT+0 News Item
Processing in Python: the future of multiprocessing

The PEP for the inclusion of pyProcessing in Python 2.6 and 3.0 has been published. This is incredibly significant for multicore programming.

No publisher Python programming multiprocessing 2008/05/30 03:05:00 GMT+0 News Item
How to automate torrent downloads using TorrentFlux-b4rt, cron and rsync

TorrentFlux-b4rt is an awesome masterpiece of engineering. You install it on your Web server, and then you can start downloading BitTorrent torrents right away. The catch is that those torrents are saved in your Web server until you actually download them to your PC. And having to schedule downloads separately is a pain. Well, no more.

Awesome awesomeness: start your downloads minutes after TorrentFlux finishes them

I've created a very, very complicated and interwoven (translation: awesome and straightforward) script that you may use and modify on your home computer. It works like this:

  • Using SSH, it queries your TorrentFlux server's transfer list, asking which torrents are completely downloaded.
  • For each of the completed torrents, it grabs the file name of the downloaded file.
  • Then, it uses rsync to incrementally transfer the downloaded file to your PC.
  • Again using rsync, it removes the file from your TorrentFlux server, freeing disk space.


What you need to do before using the script

For you to use it, you will need to do the following:

  • Enable SSH access to your (soon-to-be) TorrentFlux server.
  • Set up public key (passwordless) authentication so that your home computer's user account can freely log in to your server without asking for a password.
  • Install TorrentFlux-b4rt and set it up so that your SSH user has read/write access to the torrents and downloads folders/files. Umask/permissions, you know the drill.
  • Enable fluxcli usage on your TorrentFlux setup.
  • Install rsync on both your server and your home computer.
  • Install the BitTorrent package that contains the program named torrentinfo-console on your server.
  • Create a destination directory on your home computer.
  • Install a mail program such as mailx on your home computer.
  • Install cron on your home computer.
  • Configure the script altering the variables at the top.

Yeah, it's a lot of work. Go bitch somewhere else, we're here for the fun.


Installing the script

Put the script somewhere in your PATH. Make it executable. Set up a cron job for the purpose:

# m h  dom mon dow   command
   0,10,20,30,40,50 * * * * /home/rudd-o/bin/torrentleecher -q

Make sure the cron job line ends with a line ending (carriage return) -- otherwise it doesn't run.


The script itself

It's a stunning, hackish example of subprocessing, SSH remoting, pipeline integration, text processing, POSIX daemonizing and file locking, and samizdat logging. It gets almost all of them wrong, and yet it manages to stay standing. If you want the modern version of this program, you can find it here.

It's a miracle:

#!/usr/bin/env python
from subprocess import Popen,PIPE,STDOUT,call
import fcntl
import re
import os
import sys
import signal
import time
from threading import Thread
#FIXME: this script doesn't deal with multifile torrents
# vars!
# wherever they are used, it's MOST LIKELY they need quoting
# FIXME whatever calls SSH remoting needs to protect/quote the commands for spaces or else this might turn out to be a bitch
torrentflux_base_dir = "/home/rudd-o/vhosts/"
torrentflux_download_dir = "/home/rudd-o/vhosts/"
torrentflux_server = ""
torrentleecher_destdir = "/home/rudd-o/download/Autodownload"
fluxcli = "fluxcli"
torrentinfo = "torrentinfo-console"
email_address = "rudd-o"
def shell_quote(shellarg):
def getstdout(cmdline):
	p = Popen(cmdline,stdout=PIPE)
	output = p.communicate()[0]
	if p.returncode != 0: raise Exception, "Command %s return code %s"%(cmdline,p.returncode)
	return output
def getstdoutstderr(cmdline,inp=None): # return stoud and stderr in a single string object
	p = Popen(cmdline,stdin=PIPE,stdout=PIPE,stderr=STDOUT)
	output = p.communicate(inp)[0]
	return output
def passthru(cmdline): return call(cmdline) # return status code, pass the outputs thru
def getssh(cmd): return getstdout(["ssh","-o","BatchMode yes","-o","ForwardX11 no",torrentflux_server] + [cmd]) # return stdout of ssh.  doesn't return stderr
def sshpassthru(cmd): return call(["ssh","-o","BatchMode yes","-o","ForwardX11 no",torrentflux_server] + [cmd]) # return status code from a command executed using ssh
def mail(subject,text): return getstdoutstderr(["mail","-s",subject,email_address],text)
def get_finished_torrents():
	stdout = getssh("%s transfers"%fluxcli)
	stdout = stdout.splitlines()[2:-5]
	stdout = [ re.match("^- (.+) - [0123456789\.]+ [KMG]B - (Seeding|Done)",line) for line in stdout ]
	return [ (, ) for match in stdout if match ]
def get_file_name(torrentname):
	path = shell_quote("%s/.transfers/%s"%(
	cmd = "LANG=C %s %s"%(torrentinfo,path)
	stdout = getssh(cmd).splitlines()
	filenames = [ l[22:] for l in stdout if l.startswith("file name...........: ") ]
	if not len(filenames):
		filelistheader = stdout.index("files...............:")
		# we disregard the actual filenames, we now want the dir name
		#filenames = [ l[3:] for l in stdout[filelistheader+1:] if l.startswith("   ") ]
		filenames = [ l[22:] for l in stdout if l.startswith("directory name......: ") ]
	assert len(filenames) is 1
	return filenames[0]
def dorsync(filename,delete=False):
	# need to single-quote the *path* for the purposes of the remote shell so it doesn't fail, because the path is used in the remote shell
	path = "%s/%s"%(torrentflux_download_dir,filename)
	path = shell_quote(path)
	path = "%s:%s"%(torrentflux_server,path)
	opts = ["-arvzP"]
	if delete: opts.append("--remove-source-files")
	cmdline = [ "rsync" ] + opts + [ path , "." ]
	return passthru(cmdline)
def exists_on_server(filename):
	path = shell_quote("%s/%s"%(torrentflux_download_dir,filename))
	cmd = "test -f %s -o -d %s"%(path,path)
	returncode = sshpassthru(cmd)
	if returncode == 1: return False
	elif returncode == 0: return True
	else: raise AssertionError, "exists on server returned %s"%returncode
def remove_dirs_only(filename):
	cmd = "find %s -type d -depth -print0 | xargs -0 rmdir"%(path,)
	returncode = sshpassthru(cmd)
	if returncode == 0: return
	else: raise AssertionError, "remove dirs only returned %s"%returncode
def remove_remote_download(filename):
	cmd = "rm -fr %s"%path
	returncode = sshpassthru(cmd)
	if returncode == 0: return
def get_files_to_download():
	torrents = get_finished_torrents()
	for name,status in torrents:
		yield (name,status,get_file_name(name))
def speak(text):
	return passthru(["/usr/local/bin/swift","-n","William",text])
def lock():
	global f
	except: pass
		f=open(os.path.join(torrentleecher_destdir,".torrentleecher.lock"), 'w')
		fcntl.lockf(f.fileno(),fcntl.LOCK_EX | fcntl.LOCK_NB)
	except IOError,e:
		if e.errno == 11: return False
		else: raise
	return True
def daemonize():
	"""Detach a process from the controlling terminal and run it in the
	background as a daemon.
	try: pid = os.fork()
	except OSError, e: raise Exception, "%s [%d]" % (e.strerror, e.errno)
	if (pid == 0):		 # The first child.
		try: pid = os.fork()		  # Fork a second child.
		if (pid == 0):	 # The second child.
			# exit() or _exit()?  See below.
			os._exit(0)	 # Exit parent (the first child) of the second child.
	else: os._exit(0)		 # Exit parent of the first child.
	import resource				  # Resource usage information.
	maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
	if (maxfd == resource.RLIM_INFINITY):
		maxfd = 1024
	# Iterate through and close all file descriptors.
	for f in [ sys.stderr, sys.stdout, sys.stdin ]:
		try: f.flush()
		except: pass
	for fd in range(0, 2):
		try: os.close(fd)
		except OSError: pass
	for f in [ sys.stderr, sys.stdout, sys.stdin ]:
		try: f.close()
		except: pass
	sys.stdin = file("/dev/null", "r")
	sys.stdout = file(os.path.join(torrentleecher_destdir,".torrentleecher.log"), "a",0)
	os.dup2(1, 2)
sighandled = False
def sighandler(signum,frame):
	global sighandled
	if not sighandled:
		print "Received signal %s"%signum
		# temporarily immunize from signals
		oldhandler = signal.signal(signum,signal.SIG_IGN)
		sighandled = True
def report_file_failed(filename):
	try: os.symlink(os.path.join(torrentleecher_destdir,".torrentleecher.log"),"%s.log"%filename)
	except OSError,e:
		if e.errno != 17: raise #file exists should be ignored of course
	errortext = """Please take a look at the log files in
	mail("Leecher: error -- %s"%filename,errortext)
def set_dir_icon(filename,iconname):
	text ="""[Desktop Entry]
	try: file(os.path.join(filename,".directory"),"w").write(text)
	except: pass
def mark_dir_complete(filename): set_dir_icon(filename,"dialog-ok-apply.png")
def mark_dir_downloading(filename): set_dir_icon(filename,"document-open-remote.png")
def mark_dir_error(filename): set_dir_icon(filename,"dialog-cancel.png")
def mark_dir_downloading_when_it_appears(filename):
	def dowatch():
		starttime = time.time()
		while not os.path.isdir(filename) and time.time() - starttime < 60:
		if os.path.isdir(filename): mark_dir_downloading(filename)
	t = Thread(target=dowatch)
def speakize(filename):
		filename,extension = os.path.splitext(filename)
		if len(extension) != 3: filename = filename + "." + extension
	except ValueError: pass
	for char in "[]{}.,-_": filename = filename.replace(char," ")
	return filename
def main():
	if not ( len(sys.argv) > 1 and "-D" in sys.argv[1:] ): daemonize()
	if not lock(): # we need to lock the file after the daemonization
		if not ( len(sys.argv) > 1 and "-q" in sys.argv[1:] ):
			print "Other process is downloading the file -- add -q argument to command line to squelch this message"
		print "Starting download of finished torrents"
		for torrent,status,filename in get_files_to_download():
			# Set loop vars up
			download_lockfile = ".%s.done"%filename
			fully_downloaded = os.path.exists(download_lockfile)
			seeding = status == "Seeding"
			# If the remote files don't exist, skip
			print "Checking if %s from torrent %s exists on server"%(filename,torrent)
			if not exists_on_server(filename):
				print "%s from %s is no longer available on server, continuing to next torrent"%(filename,torrent)
			# If the download to this machine is complete, but the torrent's still seeding, skip
			if fully_downloaded:
				if seeding:
					print "%s from %s is complete but still seeding, continuing to next torrent"%(filename,torrent)
					print "Removal of %s complete"%filename
					speak ("Removal of %s complete"%speakize(filename))
				# Start download.
				print "Downloading %s from torrent %s"%(filename,torrent)
				retvalue = dorsync(filename)
				if retvalue != 0: # rsync failed
					if retvalue == 20:
						print "Download of %s stopped -- rsync process interrupted"%(filename,)
						print "Finishing by user request"
					elif retvalue < 0:
						print "Download of %s failed -- rsync process killed with signal %s"%(filename,-retvalue)
						print "Aborting"
						print "Download of %s failed -- rsync process exited with return status %s"%(filename,retvalue)
						print "Aborting"
				# Rsync successful
				# mark file as downloaded
				try: file(download_lockfile,"w").write("Done")
				except OSError,e:
					if e.errno != 17: raise
				# report successful download
				print "Download of %s complete"%filename
				speak ("Download of %s complete"%speakize(filename))
				mail("Leecher: done -- %s"%filename,"The file is at %s"%torrentleecher_destdir)
				# is it seeding?
				if not seeding:
					print "Removal of %s complete"%filename
	except Exception,e:
		report_file_failed("00 - General error")
		print "Download of finished torrents complete"
if __name__ == "__main__": main()


No publisher BitTorrent Python programming system administration automation Linux HOWTO 2007/10/31 12:40:00 GMT+0 News Item
Learn Python in 10 minutes

Yes, you too can learn Python in ten minutes. Well, at least the language. The Python standard library is... what's the term? Ah, "batteries included".

No publisher programming Python tutorials 2007/07/12 23:09:40 GMT+0 News Item