Python: launch default mail client on the system - python
I'm fairly new to Python and I'm trying to write a plugin for a text editor.
I want to know if there is a way to launch default system E-Mail client from python code.
With pywin32:
import win32api
win32api.ShellExecute(0,'open','mailto:',None,None ,0)
Update
Ah, I misread your question and presumed you're on Win platform.
A platform independent solution would be open mailto link in a browser, like
import webbrowser
webbrowser.open('mailto:', new=1)
Update 2
Some additional research (in fact, first two pages of google search) revealed this excellent snippet:
#!/usr/bin/env python
'''Utilities for opening files or URLs in the registered default application
and for sending e-mail using the user's preferred composer.
'''
__version__ = '1.1'
__all__ = ['open', 'mailto']
import os
import sys
import webbrowser
import subprocess
from email.Utils import encode_rfc2231
_controllers = {}
_open = None
class BaseController(object):
'''Base class for open program controllers.'''
def __init__(self, name):
self.name = name
def open(self, filename):
raise NotImplementedError
class Controller(BaseController):
'''Controller for a generic open program.'''
def __init__(self, *args):
super(Controller, self).__init__(os.path.basename(args[0]))
self.args = list(args)
def _invoke(self, cmdline):
if sys.platform[:3] == 'win':
closefds = False
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
else:
closefds = True
startupinfo = None
if (os.environ.get('DISPLAY') or sys.platform[:3] == 'win' or
sys.platform == 'darwin'):
inout = file(os.devnull, 'r+')
else:
# for TTY programs, we need stdin/out
inout = None
# if possible, put the child precess in separate process group,
# so keyboard interrupts don't affect child precess as well as
# Python
setsid = getattr(os, 'setsid', None)
if not setsid:
setsid = getattr(os, 'setpgrp', None)
pipe = subprocess.Popen(cmdline, stdin=inout, stdout=inout,
stderr=inout, close_fds=closefds,
preexec_fn=setsid, startupinfo=startupinfo)
# It is assumed that this kind of tools (gnome-open, kfmclient,
# exo-open, xdg-open and open for OSX) immediately exit after lauching
# the specific application
returncode = pipe.wait()
if hasattr(self, 'fixreturncode'):
returncode = self.fixreturncode(returncode)
return not returncode
def open(self, filename):
if isinstance(filename, basestring):
cmdline = self.args + [filename]
else:
# assume it is a sequence
cmdline = self.args + filename
try:
return self._invoke(cmdline)
except OSError:
return False
# Platform support for Windows
if sys.platform[:3] == 'win':
class Start(BaseController):
'''Controller for the win32 start progam through os.startfile.'''
def open(self, filename):
try:
os.startfile(filename)
except WindowsError:
# [Error 22] No application is associated with the specified
# file for this operation: '<URL>'
return False
else:
return True
_controllers['windows-default'] = Start('start')
_open = _controllers['windows-default'].open
# Platform support for MacOS
elif sys.platform == 'darwin':
_controllers['open']= Controller('open')
_open = _controllers['open'].open
# Platform support for Unix
else:
import commands
# #WARNING: use the private API of the webbrowser module
from webbrowser import _iscommand
class KfmClient(Controller):
'''Controller for the KDE kfmclient program.'''
def __init__(self, kfmclient='kfmclient'):
super(KfmClient, self).__init__(kfmclient, 'exec')
self.kde_version = self.detect_kde_version()
def detect_kde_version(self):
kde_version = None
try:
info = commands.getoutput('kde-config --version')
for line in info.splitlines():
if line.startswith('KDE'):
kde_version = line.split(':')[-1].strip()
break
except (OSError, RuntimeError):
pass
return kde_version
def fixreturncode(self, returncode):
if returncode is not None and self.kde_version > '3.5.4':
return returncode
else:
return os.EX_OK
def detect_desktop_environment():
'''Checks for known desktop environments
Return the desktop environments name, lowercase (kde, gnome, xfce)
or "generic"
'''
desktop_environment = 'generic'
if os.environ.get('KDE_FULL_SESSION') == 'true':
desktop_environment = 'kde'
elif os.environ.get('GNOME_DESKTOP_SESSION_ID'):
desktop_environment = 'gnome'
else:
try:
info = commands.getoutput('xprop -root _DT_SAVE_MODE')
if ' = "xfce4"' in info:
desktop_environment = 'xfce'
except (OSError, RuntimeError):
pass
return desktop_environment
def register_X_controllers():
if _iscommand('kfmclient'):
_controllers['kde-open'] = KfmClient()
for command in ('gnome-open', 'exo-open', 'xdg-open'):
if _iscommand(command):
_controllers[command] = Controller(command)
def get():
controllers_map = {
'gnome': 'gnome-open',
'kde': 'kde-open',
'xfce': 'exo-open',
}
desktop_environment = detect_desktop_environment()
try:
controller_name = controllers_map[desktop_environment]
return _controllers[controller_name].open
except KeyError:
if _controllers.has_key('xdg-open'):
return _controllers['xdg-open'].open
else:
return webbrowser.open
if os.environ.get("DISPLAY"):
register_X_controllers()
_open = get()
def open(filename):
'''Open a file or an URL in the registered default application.'''
return _open(filename)
def _fix_addersses(**kwargs):
for headername in ('address', 'to', 'cc', 'bcc'):
try:
headervalue = kwargs[headername]
if not headervalue:
del kwargs[headername]
continue
elif not isinstance(headervalue, basestring):
# assume it is a sequence
headervalue = ','.join(headervalue)
except KeyError:
pass
except TypeError:
raise TypeError('string or sequence expected for "%s", '
'%s found' % (headername,
type(headervalue).__name__))
else:
translation_map = {'%': '%25', '&': '%26', '?': '%3F'}
for char, replacement in translation_map.items():
headervalue = headervalue.replace(char, replacement)
kwargs[headername] = headervalue
return kwargs
def mailto_format(**kwargs):
# #TODO: implement utf8 option
kwargs = _fix_addersses(**kwargs)
parts = []
for headername in ('to', 'cc', 'bcc', 'subject', 'body', 'attach'):
if kwargs.has_key(headername):
headervalue = kwargs[headername]
if not headervalue:
continue
if headername in ('address', 'to', 'cc', 'bcc'):
parts.append('%s=%s' % (headername, headervalue))
else:
headervalue = encode_rfc2231(headervalue) # #TODO: check
parts.append('%s=%s' % (headername, headervalue))
mailto_string = 'mailto:%s' % kwargs.get('address', '')
if parts:
mailto_string = '%s?%s' % (mailto_string, '&'.join(parts))
return mailto_string
def mailto(address, to=None, cc=None, bcc=None, subject=None, body=None,
attach=None):
'''Send an e-mail using the user's preferred composer.
Open the user's preferred e-mail composer in order to send a mail to
address(es) that must follow the syntax of RFC822. Multiple addresses
may be provided (for address, cc and bcc parameters) as separate
arguments.
All parameters provided are used to prefill corresponding fields in
the user's e-mail composer. The user will have the opportunity to
change any of this information before actually sending the e-mail.
address - specify the destination recipient
cc - specify a recipient to be copied on the e-mail
bcc - specify a recipient to be blindly copied on the e-mail
subject - specify a subject for the e-mail
body - specify a body for the e-mail. Since the user will be able
to make changes before actually sending the e-mail, this
can be used to provide the user with a template for the
e-mail text may contain linebreaks
attach - specify an attachment for the e-mail. file must point to
an existing file
'''
mailto_string = mailto_format(**locals())
return open(mailto_string)
if __name__ == '__main__':
from optparse import OptionParser
version = '%%prog %s' % __version__
usage = (
'\n\n%prog FILENAME [FILENAME(s)] -- for opening files'
'\n\n%prog -m [OPTIONS] ADDRESS [ADDRESS(es)] -- for sending e-mails'
)
parser = OptionParser(usage=usage, version=version, description=__doc__)
parser.add_option('-m', '--mailto', dest='mailto_mode', default=False,
action='store_true', help='set mailto mode. '
'If not set any other option is ignored')
parser.add_option('--cc', dest='cc', help='specify a recipient to be '
'copied on the e-mail')
parser.add_option('--bcc', dest='bcc', help='specify a recipient to be '
'blindly copied on the e-mail')
parser.add_option('--subject', dest='subject',
help='specify a subject for the e-mail')
parser.add_option('--body', dest='body', help='specify a body for the '
'e-mail. Since the user will be able to make changes '
'before actually sending the e-mail, this can be used '
'to provide the user with a template for the e-mail '
'text may contain linebreaks')
parser.add_option('--attach', dest='attach', help='specify an attachment '
'for the e-mail. file must point to an existing file')
(options, args) = parser.parse_args()
if not args:
parser.print_usage()
parser.exit(1)
if options.mailto_mode:
if not mailto(args, None, options.cc, options.bcc, options.subject,
options.body, options.attach):
sys.exit('Unable to open the e-mail client')
else:
for name in ('cc', 'bcc', 'subject', 'body', 'attach'):
if getattr(options, name):
parser.error('The "cc", "bcc", "subject", "body" and "attach" '
'options are only accepten in mailto mode')
success = False
for arg in args:
if not open(arg):
print 'Unable to open "%s"' % arg
else:
success = True
sys.exit(success)
Enjoy.
The above-mentioned code only works in Python 2.
I've modified it to work for Python 3. The "attach" parameter is no longer supported for security reasons.
#!/usr/bin/env python3
'''Utilities for opening files or URLs in the registered default application
and for sending e-mail using the user's preferred composer.
https://stackoverflow.com/a/19779373/3211506
'''
__version__ = '1.1'
__all__ = ['open', 'mailto']
import os
import sys
import webbrowser
import subprocess
from email.utils import encode_rfc2231
_controllers = {}
_open = None
fileopen = open
class BaseController(object):
'''Base class for open program controllers.'''
def __init__(self, name):
self.name = name
def open(self, filename):
raise NotImplementedError
class Controller(BaseController):
'''Controller for a generic open program.'''
def __init__(self, *args):
super(Controller, self).__init__(os.path.basename(args[0]))
self.args = list(args)
def _invoke(self, cmdline):
if sys.platform[:3] == 'win':
closefds = False
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
else:
closefds = True
startupinfo = None
if (os.environ.get('DISPLAY') or sys.platform[:3] == 'win' or
sys.platform == 'darwin'):
inout = fileopen(os.devnull, 'r+')
else:
# for TTY programs, we need stdin/out
inout = None
# if possible, put the child precess in separate process group,
# so keyboard interrupts don't affect child precess as well as
# Python
setsid = getattr(os, 'setsid', None)
if not setsid:
setsid = getattr(os, 'setpgrp', None)
pipe = subprocess.Popen(cmdline, stdin=inout, stdout=inout,
stderr=inout, close_fds=closefds,
preexec_fn=setsid, startupinfo=startupinfo)
# It is assumed that this kind of tools (gnome-open, kfmclient,
# exo-open, xdg-open and open for OSX) immediately exit after lauching
# the specific application
returncode = pipe.wait()
if hasattr(self, 'fixreturncode'):
returncode = self.fixreturncode(returncode)
return not returncode
def open(self, filename):
if isinstance(filename, str):
cmdline = self.args + [filename]
else:
# assume it is a sequence
cmdline = self.args + filename
try:
return self._invoke(cmdline)
except OSError:
return False
# Platform support for Windows
if sys.platform[:3] == 'win':
class Start(BaseController):
'''Controller for the win32 start progam through os.startfile.'''
def open(self, filename):
try:
os.startfile(filename)
except WindowsError:
# [Error 22] No application is associated with the specified
# file for this operation: '<URL>'
return False
else:
return True
_controllers['windows-default'] = Start('start')
_open = _controllers['windows-default'].open
# Platform support for MacOS
elif sys.platform == 'darwin':
_controllers['open']= Controller('open')
_open = _controllers['open'].open
# Platform support for Unix
else:
import subprocess, stat
# #WARNING: use the private API of the webbrowser module
# from webbrowser import _iscommand
def _isexecutable(cmd):
if os.path.isfile(cmd):
mode = os.stat(cmd)[stat.ST_MODE]
if mode & stat.S_IXUSR or mode & stat.S_IXGRP or mode & stat.S_IXOTH:
return True
return False
def _iscommand(cmd):
"""Return True if cmd is executable or can be found on the executable
search path."""
if _isexecutable(cmd):
return True
path = os.environ.get("PATH")
if not path:
return False
for d in path.split(os.pathsep):
exe = os.path.join(d, cmd)
if _isexecutable(exe):
return True
return False
class KfmClient(Controller):
'''Controller for the KDE kfmclient program.'''
def __init__(self, kfmclient='kfmclient'):
super(KfmClient, self).__init__(kfmclient, 'exec')
self.kde_version = self.detect_kde_version()
def detect_kde_version(self):
kde_version = None
try:
info = subprocess.getoutput('kde-config --version')
for line in info.splitlines():
if line.startswith('KDE'):
kde_version = line.split(':')[-1].strip()
break
except (OSError, RuntimeError):
pass
return kde_version
def fixreturncode(self, returncode):
if returncode is not None and self.kde_version > '3.5.4':
return returncode
else:
return os.EX_OK
def detect_desktop_environment():
'''Checks for known desktop environments
Return the desktop environments name, lowercase (kde, gnome, xfce)
or "generic"
'''
desktop_environment = 'generic'
if os.environ.get('KDE_FULL_SESSION') == 'true':
desktop_environment = 'kde'
elif os.environ.get('GNOME_DESKTOP_SESSION_ID'):
desktop_environment = 'gnome'
else:
try:
info = subprocess.getoutput('xprop -root _DT_SAVE_MODE')
if ' = "xfce4"' in info:
desktop_environment = 'xfce'
except (OSError, RuntimeError):
pass
return desktop_environment
def register_X_controllers():
if _iscommand('kfmclient'):
_controllers['kde-open'] = KfmClient()
for command in ('gnome-open', 'exo-open', 'xdg-open'):
if _iscommand(command):
_controllers[command] = Controller(command)
def get():
controllers_map = {
'gnome': 'gnome-open',
'kde': 'kde-open',
'xfce': 'exo-open',
}
desktop_environment = detect_desktop_environment()
try:
controller_name = controllers_map[desktop_environment]
return _controllers[controller_name].open
except KeyError:
if 'xdg-open' in _controllers:
return _controllers['xdg-open'].open
else:
return webbrowser.open
if os.environ.get("DISPLAY"):
register_X_controllers()
_open = get()
def open(filename):
'''Open a file or an URL in the registered default application.'''
return _open(filename)
def _fix_addersses(**kwargs):
for headername in ('address', 'to', 'cc', 'bcc'):
try:
headervalue = kwargs[headername]
if not headervalue:
del kwargs[headername]
continue
elif not isinstance(headervalue, str):
# assume it is a sequence
headervalue = ','.join(headervalue)
except KeyError:
pass
except TypeError:
raise TypeError('string or sequence expected for "%s", '
'%s found' % (headername,
type(headervalue).__name__))
else:
translation_map = {'%': '%25', '&': '%26', '?': '%3F'}
for char, replacement in list(translation_map.items()):
headervalue = headervalue.replace(char, replacement)
kwargs[headername] = headervalue
return kwargs
def mailto_format(**kwargs):
# #TODO: implement utf8 option
kwargs = _fix_addersses(**kwargs)
parts = []
for headername in ('to', 'cc', 'bcc', 'subject', 'body'):
if headername in kwargs:
headervalue = kwargs[headername]
if not headervalue:
continue
if headername in ('address', 'to', 'cc', 'bcc'):
parts.append('%s=%s' % (headername, headervalue))
else:
headervalue = encode_rfc2231(headervalue, charset="utf-8")[7:] # #TODO: check
parts.append('%s=%s' % (headername, headervalue))
mailto_string = 'mailto:%s' % kwargs.get('address', '')
if parts:
mailto_string = '%s?%s' % (mailto_string, '&'.join(parts))
return mailto_string
def mailto(address, to=None, cc=None, bcc=None, subject=None, body=None):
'''Send an e-mail using the user's preferred composer.
Open the user's preferred e-mail composer in order to send a mail to
address(es) that must follow the syntax of RFC822. Multiple addresses
may be provided (for address, cc and bcc parameters) as separate
arguments.
All parameters provided are used to prefill corresponding fields in
the user's e-mail composer. The user will have the opportunity to
change any of this information before actually sending the e-mail.
address - specify the destination recipient
cc - specify a recipient to be copied on the e-mail
bcc - specify a recipient to be blindly copied on the e-mail
subject - specify a subject for the e-mail
body - specify a body for the e-mail. Since the user will be able
to make changes before actually sending the e-mail, this
can be used to provide the user with a template for the
e-mail text may contain linebreaks
attach - specify an attachment for the e-mail. file must point to
an existing file (UNSUPPORTED)
'''
mailto_string = mailto_format(**locals())
return open(mailto_string)
if __name__ == '__main__':
from optparse import OptionParser
version = '%%prog %s' % __version__
usage = (
'\n\n%prog FILENAME [FILENAME(s)] -- for opening files'
'\n\n%prog -m [OPTIONS] ADDRESS [ADDRESS(es)] -- for sending e-mails'
)
parser = OptionParser(usage=usage, version=version, description=__doc__)
parser.add_option('-m', '--mailto', dest='mailto_mode', default=False,
action='store_true', help='set mailto mode. '
'If not set any other option is ignored')
parser.add_option('--cc', dest='cc', help='specify a recipient to be '
'copied on the e-mail')
parser.add_option('--bcc', dest='bcc', help='specify a recipient to be '
'blindly copied on the e-mail')
parser.add_option('--subject', dest='subject',
help='specify a subject for the e-mail')
parser.add_option('--body', dest='body', help='specify a body for the '
'e-mail. Since the user will be able to make changes '
'before actually sending the e-mail, this can be used '
'to provide the user with a template for the e-mail '
'text may contain linebreaks')
parser.add_option('--attach', dest='attach', help='specify an attachment '
'for the e-mail. file must point to an existing file')
(options, args) = parser.parse_args()
if not args:
parser.print_usage()
parser.exit(1)
if options.mailto_mode:
if not mailto(args, None, options.cc, options.bcc, options.subject,
options.body, options.attach):
sys.exit('Unable to open the e-mail client')
else:
for name in ('cc', 'bcc', 'subject', 'body', 'attach'):
if getattr(options, name):
parser.error('The "cc", "bcc", "subject", "body" and "attach" '
'options are only accepten in mailto mode')
success = False
for arg in args:
if not open(arg):
print('Unable to open "%s"' % arg)
else:
success = True
sys.exit(success)
Related
WaitForSingleObject not working - invalid handle
I'm currently righting a code for client that can download files from a cloud. The client downloads the file temporarily and when the file is closed (terminated) it gets sent back to the cloud. Here is the full code: import socket import os from OpenFile import * from Registry_Change import * import win32con import win32api import win32event from win32com.shell import shellcon from win32com.shell.shell import ShellExecuteEx class Application(object): def __init__(self): """ :param request: the request of the file to receive from server """ # initiates request (clicked file path) self.request = sys.argv[SECOND] reg = Read_Registry() ip, port = reg.get_ip_port() self.ip = ip self.port = port # initiates socket try: self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock.connect((self.ip, self.port)) # sends the request to the server Application.send_request_to_server(self.sock, "DOWNLOAD_FILE " + self.request) format = Application.read_server_response(self.sock).decode() self.path_file = self.download(format) self.start_file_and_wait() self.sock.close() except Exception as msg: print(win32api.GetLastError()) print("connection error:", msg) #staticmethod def valid_file(path): """ checks if the path is a file that exists """ if os.path.isfile(path): return True return False #staticmethod def delete_file(file_path): """ deletes file """ os.remove(file_path) #staticmethod def read_server_response(server_socket_choice): """ reads the length and according to that, it reads the rest of the message """ try: length_of_message = server_socket_choice.recv(BYTE).decode() if length_of_message.isdigit(): return server_socket_choice.recv(int(length_of_message)) except Exception as msg: print("at read_server_response:", msg) return SERVER_FELL #staticmethod def send_request_to_server(server_socket, request): """ Send the request to the server. First the length of the request (2 digits), then the request itself Example: '04EXIT' Example: '12DIR c:\cyber' """ server_socket. \ send((str(len(request)).zfill(MSG_FILL) + request).encode()) def download(self, format): """ saves the given chunks to a file in the client """ try: file = Application.new_format_path(self.request, format) new_location = Application.make_new_file_path(TEMPORARY_FILES, file) # check if the file is valid check_len = self.sock.recv(BYTE).decode() check = self.sock.recv(int(check_len)) if check != FILE_DOESNT_EXIST: client_file = open(new_location, 'wb') # write what we took out client_file.write(check) done = False while not done: byte_message_len = self.sock.recv(BYTE) length = byte_message_len.decode() if length.isdigit(): real_len = int(length) data = self.sock.recv(real_len) if data == FILE_END: done = True else: client_file.write(data) client_file.close() return new_location else: return 'nothing' except Exception as msg: print("at download:", msg) def upload(self, file_path): """ Sends a file from the server to the client """ if Application.valid_file(file_path): client_file = open(file_path, 'rb') content = client_file.read(BYTE_NUMBER) while content != b'': Application.send_binary_response_to_server(content, self.sock) content = client_file.read(BYTE_NUMBER) client_file.close() Application.send_binary_response_to_server(FILE_END, self.sock) Application.delete_file(file_path) Application.make_imaginary_file(file_path) return Application.read_server_response(self.my_socket) else: Application.send_response_to_server(FILE_DOESNT_EXIST, self.sock) return FILE_DOESNT_EXIST #staticmethod def make_new_file_path(new_path, folder): """ :param new_path: new path of file to merge :return: the new path """ comp = folder.split("\\") return new_path + "\\" + comp[END] #staticmethod def new_format_path(path, format): """ :param format: the new format :return: the same path but with new format """ path_format = path.split('.') path_format[SECOND] = format return ".".join(path_format) def start_file_and_wait(self): """ :param fname: the file path - temporary :return: opens and continues when closed """ rc = ShellExecuteEx( fMask=shellcon.SEE_MASK_NOCLOSEPROCESS, nShow=win32con.SW_SHOW, lpFile=self.path_file) hproc = rc['hProcess'] win32event.WaitForSingleObject(hproc, win32event.INFINITE) win32api.CloseHandle(hproc) app = Application() Now, the win32event.WaitForSingleObject(hproc, win32event.INFINITE) command does not work, and returns the error: "(6, 'WaitForSingleObject', 'The handle is invalid.')". When I tried to use the start_file_and_wait(self) function in a separate file, it worked: def start_file_wait(fname): import win32con import win32api import win32event from win32com.shell import shellcon from win32com.shell.shell import ShellExecuteEx rc = ShellExecuteEx( fMask=shellcon.SEE_MASK_NOCLOSEPROCESS, nShow=win32con.SW_SHOW, lpFile=fname) hproc = rc['hProcess'] win32event.WaitForSingleObject(hproc, win32event.INFINITE) win32api.CloseHandle(hproc) def main(): start_file_wait("E:\\12\\alice-chapter-1.txt") print("hi") if __name__ == '__main__': main() I don't know how to fix it. can someone help me? Thanks!
It doesn't work on files that aren't text files As you said, You did not specify a suitable verb for ShellExecuteEx, according to the parameter: lpVerb : ... This parameter can be NULL, in which case the default verb is used if available. If not, the "open" verb is used. If neither verb is available, the system uses the first verb listed in the registry. It may fail and return an invalid hProcess handle if it cannot find the associated application to open the file. You should specify a valid verb according to the file you open. Or specify the executable file of the app corresponding to the file as lpFile, and specify the file as lpParameters. You could refer to the following document: Launching Applications
yowsup - Integrating sending and receiving
Background: I would like to integrate yowsup to my home automation project. I have seen a simple sample on how to receive messages and after some minor changes it is working fine. Issue: My problem starts when it comes to integrate the send message feature. Those are the two files I am using: run.py from layer import EchoLayer from yowsup.layers.auth import YowAuthenticationProtocolLayer from yowsup.layers.protocol_messages import YowMessagesProtocolLayer from yowsup.layers.protocol_receipts import YowReceiptProtocolLayer from yowsup.layers.protocol_acks import YowAckProtocolLayer from yowsup.layers.protocol_presence import YowPresenceProtocolLayer from yowsup.layers.network import YowNetworkLayer from yowsup.layers.coder import YowCoderLayer from yowsup.common import YowConstants from yowsup.layers import YowLayerEvent from yowsup.stacks import YowStack, YOWSUP_CORE_LAYERS from yowsup import env CREDENTIALS = ("phone", "pwd") if __name__ == "__main__": layers = ( EchoLayer, (YowAuthenticationProtocolLayer, YowMessagesProtocolLayer, YowReceiptProtocolLayer, YowAckProtocolLayer, YowPresenceProtocolLayer) ) + YOWSUP_CORE_LAYERS stack = YowStack(layers) # Setting credentials stack.setProp(YowAuthenticationProtocolLayer.PROP_CREDENTIALS, CREDENTIALS) # WhatsApp server address stack.setProp(YowNetworkLayer.PROP_ENDPOINT, YowConstants.ENDPOINTS[0]) stack.setProp(YowCoderLayer.PROP_DOMAIN, YowConstants.DOMAIN) stack.setProp(YowCoderLayer.PROP_RESOURCE, env.CURRENT_ENV.getResource()) # Sending connecting signal stack.broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_CONNECT)) # Program main loop stack.loop() layer.py from yowsup.layers.interface import YowInterfaceLayer, ProtocolEntityCallback from yowsup.layers.protocol_messages.protocolentities import TextMessageProtocolEntity from yowsup.layers.protocol_receipts.protocolentities import OutgoingReceiptProtocolEntity from yowsup.layers.protocol_acks.protocolentities import OutgoingAckProtocolEntity from yowsup.layers.protocol_presence.protocolentities import PresenceProtocolEntity import threading import logging logger = logging.getLogger(__name__) class EchoLayer(YowInterfaceLayer): #ProtocolEntityCallback("message") def onMessage(self, messageProtocolEntity): #send receipt otherwise we keep receiving the same message over and over print str(messageProtocolEntity.getFrom()) + ' - ' + str(messageProtocolEntity.getBody()) receipt = OutgoingReceiptProtocolEntity(messageProtocolEntity.getId(), messageProtocolEntity.getFrom()) self.toLower(receipt) #ProtocolEntityCallback("send_message") def sendMessage(self, destination, message, messageProtocolEntity): outgoingMessageProtocolEntity = TextMessageProtocolEntity( message, to = destination + "#s.whatsapp.net") self.toLower(outgoingMessageProtocolEntity) #ProtocolEntityCallback("receipt") def onReceipt(self, entity): ack = OutgoingAckProtocolEntity(entity.getId(), "receipt", "delivery") self.toLower(ack) # List of (jid, message) tuples PROP_MESSAGES = "org.openwhatsapp.yowsup.prop.sendclient.queue" def __init__(self): super(EchoLayer, self).__init__() self.ackQueue = [] self.lock = threading.Condition() #ProtocolEntityCallback("success") def onSuccess(self, successProtocolEntity): self.lock.acquire() for target in self.getProp(self.__class__.PROP_MESSAGES, []): phone, message = target if '#' in phone: messageEntity = TextMessageProtocolEntity(message, to = phone) elif '-' in phone: messageEntity = TextMessageProtocolEntity(message, to = "%s#g.us" % phone) else: messageEntity = TextMessageProtocolEntity(message, to = "%s#s.whatsapp.net" % phone) self.ackQueue.append(messageEntity.getId()) self.toLower(messageEntity) self.lock.release() #ProtocolEntityCallback("ack") def onAck(self, entity): self.lock.acquire() if entity.getId() in self.ackQueue: self.ackQueue.pop(self.ackQueue.index(entity.getId())) if not len(self.ackQueue): logger.info("Message sent") #raise KeyboardInterrupt() self.lock.release() Questions: Where am I supposed to call the send_message method, so I can send messages wherever I need it? Is there a regular event (triggering every second or something) which I could use to send my messages?
#ProtocolEntityCallback("send_message") def sendMessage(self, destination, message, messageProtocolEntity): outgoingMessageProtocolEntity = TextMessageProtocolEntity( message, to = destination + "#s.whatsapp.net") self.toLower(outgoingMessageProtocolEntity) In the avove code sendMessage to be called, protocolEntity.getTag() == "send_message" has to be True. You don't need it to send message. layer.py from yowsup.layers.interface import YowInterfaceLayer, ProtocolEntityCallback from yowsup.layers.protocol_messages.protocolentities import TextMessageProtocolEntity from yowsup.layers.protocol_receipts.protocolentities import OutgoingReceiptProtocolEntity from yowsup.layers.protocol_acks.protocolentities import OutgoingAckProtocolEntity from yowsup.layers.protocol_presence.protocolentities import PresenceProtocolEntity import threading import logging logger = logging.getLogger(__name__) recv_msg = [] class EchoLayer(YowInterfaceLayer): def __init__(self): super(EchoLayer, self).__init__() self.ackQueue = [] self.lock = threading.Condition() #ProtocolEntityCallback("message") def onMessage(self, messageProtocolEntity): if messageProtocolEntity.getType() == 'text': recv_msg.append((messageProtocolEntity.getFrom(),messageProtocolEntity.getBody())) #send receipt otherwise we keep receiving the same message over and over receipt = OutgoingReceiptProtocolEntity(messageProtocolEntity.getId(), messageProtocolEntity.getFrom()) self.toLower(receipt) #ProtocolEntityCallback("receipt") def onReceipt(self, entity): ack = OutgoingAckProtocolEntity(entity.getId(), "receipt", "delivery") self.toLower(ack) # List of (jid, message) tuples PROP_MESSAGES = "org.openwhatsapp.yowsup.prop.sendclient.queue" #ProtocolEntityCallback("success") def onSuccess(self, successProtocolEntity): self.lock.acquire() for target in self.getProp(self.__class__.PROP_MESSAGES, []): phone, message = target if '#' in phone: messageEntity = TextMessageProtocolEntity(message, to = phone) elif '-' in phone: messageEntity = TextMessageProtocolEntity(message, to = "%s#g.us" % phone) else: messageEntity = TextMessageProtocolEntity(message, to = "%s#s.whatsapp.net" % phone) self.ackQueue.append(messageEntity.getId()) self.toLower(messageEntity) self.lock.release() #ProtocolEntityCallback("ack") def onAck(self, entity): self.lock.acquire() if entity.getId() in self.ackQueue: self.ackQueue.pop(self.ackQueue.index(entity.getId())) if not len(self.ackQueue): self.lock.release() logger.info("Message sent") raise KeyboardInterrupt() self.lock.release() To send message define a function send_message in the stack run.py. You can also import run.py and use it's function from other script. from layer import EchoLayer, recv_msg CREDENTIALS = ("phone", "pwd") def send_message(destination, message): ''' destination is <phone number> without '+' and with country code of type string, message is string e.g send_message('11133434343','hello') ''' messages = [(destination, message)] layers = (EchoLayer, (YowAuthenticationProtocolLayer, YowMessagesProtocolLayer, YowReceiptProtocolLayer, YowAckProtocolLayer, YowPresenceProtocolLayer) ) + YOWSUP_CORE_LAYERS stack = YowStack(layers) stack.setProp(EchoLayer.PROP_MESSAGES, messages) stack.setProp(YowAuthenticationProtocolLayer.PROP_PASSIVE, True) # Setting credentials stack.setProp(YowAuthenticationProtocolLayer.PROP_CREDENTIALS, CREDENTIALS) # WhatsApp server address stack.setProp(YowNetworkLayer.PROP_ENDPOINT, YowConstants.ENDPOINTS[0]) stack.setProp(YowCoderLayer.PROP_DOMAIN, YowConstants.DOMAIN) stack.setProp(YowCoderLayer.PROP_RESOURCE, env.CURRENT_ENV.getResource()) # Sending connecting signal stack.broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_CONNECT)) try: # Program main loop stack.loop() except AuthError as e: print('Authentication error %s' % e.message) sys.exit(1) def recv_message(): layers = ( EchoLayer, (YowAuthenticationProtocolLayer, YowMessagesProtocolLayer, YowReceiptProtocolLayer, YowAckProtocolLayer, YowPresenceProtocolLayer) ) + YOWSUP_CORE_LAYERS stack = YowStack(layers) # Setting credentials stack.setProp(YowAuthenticationProtocolLayer.PROP_CREDENTIALS, CREDENTIALS) # WhatsApp server address stack.setProp(YowNetworkLayer.PROP_ENDPOINT, YowConstants.ENDPOINTS[0]) stack.setProp(YowCoderLayer.PROP_DOMAIN, YowConstants.DOMAIN) stack.setProp(YowCoderLayer.PROP_RESOURCE, env.CURRENT_ENV.getResource()) # Sending connecting signal stack.broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_CONNECT)) try: # Program main loop stack.loop() except AuthError as e: print('Authentication error %s' % e.message) sys.exit(1) if __name__ == '__main__': if len(sys.argv) == 1: print('%s send number message\nrecv\n' % sys.argv[0]) sys.exit(1) if sys.argv[1] == 'send': try: send_message(sys.argv[2],sys.argv[3]) except KeyboardInterrupt: print('closing') sys.exit(0) if sys.argv[1] == 'recv': try: recv_message() except KeyboardInterrupt: print('closing') sys.exit(0) for m in recv_msg: print('From %s:\n%s\n' % m) Now you can send message by calling send_message('1234567890','Howdy') and recieve message by calling recv_message().
import python with __main__ method
I have a python script that have __main__ statement and took all values parametric. I want to import and use it in my own script. Actually I can import but don't know how to use it. As you see below, __main__ is a bit complicated and rewriting it will take time because I even don't know what does most of code mean. Want to know is there any way to import and use the code as a function? import os import sys import time import base64 from urllib2 import urlopen from urllib2 import Request from urllib2 import HTTPError from urllib import urlencode from urllib import quote from exceptions import Exception from email.mime.multipart import MIMEMultipart from email.mime.base import MIMEBase from email.mime.application import MIMEApplication from email.encoders import encode_noop from api_util import json2python, python2json class MalformedResponse(Exception): pass class RequestError(Exception): pass class Client(object): default_url = 'http://nova.astrometry.net/api/' def __init__(self, apiurl = default_url): self.session = None self.apiurl = apiurl def get_url(self, service): return self.apiurl + service def send_request(self, service, args={}, file_args=None): ''' service: string args: dict ''' if self.session is not None: args.update({ 'session' : self.session }) print 'Python:', args json = python2json(args) print 'Sending json:', json url = self.get_url(service) print 'Sending to URL:', url # If we're sending a file, format a multipart/form-data if file_args is not None: m1 = MIMEBase('text', 'plain') m1.add_header('Content-disposition', 'form-data; name="request-json"') m1.set_payload(json) m2 = MIMEApplication(file_args[1],'octet-stream',encode_noop) m2.add_header('Content-disposition', 'form-data; name="file"; filename="%s"' % file_args[0]) #msg.add_header('Content-Disposition', 'attachment', # filename='bud.gif') #msg.add_header('Content-Disposition', 'attachment', # filename=('iso-8859-1', '', 'FuSballer.ppt')) mp = MIMEMultipart('form-data', None, [m1, m2]) # Makie a custom generator to format it the way we need. from cStringIO import StringIO from email.generator import Generator class MyGenerator(Generator): def __init__(self, fp, root=True): Generator.__init__(self, fp, mangle_from_=False, maxheaderlen=0) self.root = root def _write_headers(self, msg): # We don't want to write the top-level headers; # they go into Request(headers) instead. if self.root: return # We need to use \r\n line-terminator, but Generator # doesn't provide the flexibility to override, so we # have to copy-n-paste-n-modify. for h, v in msg.items(): print >> self._fp, ('%s: %s\r\n' % (h,v)), # A blank line always separates headers from body print >> self._fp, '\r\n', # The _write_multipart method calls "clone" for the # subparts. We hijack that, setting root=False def clone(self, fp): return MyGenerator(fp, root=False) fp = StringIO() g = MyGenerator(fp) g.flatten(mp) data = fp.getvalue() headers = {'Content-type': mp.get('Content-type')} if False: print 'Sending headers:' print ' ', headers print 'Sending data:' print data[:1024].replace('\n', '\\n\n').replace('\r', '\\r') if len(data) > 1024: print '...' print data[-256:].replace('\n', '\\n\n').replace('\r', '\\r') print else: # Else send x-www-form-encoded data = {'request-json': json} print 'Sending form data:', data data = urlencode(data) print 'Sending data:', data headers = {} request = Request(url=url, headers=headers, data=data) try: f = urlopen(request) txt = f.read() print 'Got json:', txt result = json2python(txt) print 'Got result:', result stat = result.get('status') print 'Got status:', stat if stat == 'error': errstr = result.get('errormessage', '(none)') raise RequestError('server error message: ' + errstr) return result except HTTPError, e: print 'HTTPError', e txt = e.read() open('err.html', 'wb').write(txt) print 'Wrote error text to err.html' def login(self, apikey): args = { 'apikey' : apikey } result = self.send_request('login', args) sess = result.get('session') print 'Got session:', sess if not sess: raise RequestError('no session in result') self.session = sess def _get_upload_args(self, **kwargs): args = {} for key,default,typ in [('allow_commercial_use', 'd', str), ('allow_modifications', 'd', str), ('publicly_visible', 'y', str), ('scale_units', None, str), ('scale_type', None, str), ('scale_lower', None, float), ('scale_upper', None, float), ('scale_est', None, float), ('scale_err', None, float), ('center_ra', None, float), ('center_dec', None, float), ('radius', None, float), ('downsample_factor', None, int), ('tweak_order', None, int), ('crpix_center', None, bool), # image_width, image_height ]: if key in kwargs: val = kwargs.pop(key) val = typ(val) args.update({key: val}) elif default is not None: args.update({key: default}) print 'Upload args:', args return args def url_upload(self, url, **kwargs): args = dict(url=url) args.update(self._get_upload_args(**kwargs)) result = self.send_request('url_upload', args) return result def upload(self, fn, **kwargs): args = self._get_upload_args(**kwargs) try: f = open(fn, 'rb') result = self.send_request('upload', args, (fn, f.read())) return result except IOError: print 'File %s does not exist' % fn raise def submission_images(self, subid): result = self.send_request('submission_images', {'subid':subid}) return result.get('image_ids') def overlay_plot(self, service, outfn, wcsfn, wcsext=0): from astrometry.util import util as anutil wcs = anutil.Tan(wcsfn, wcsext) params = dict(crval1 = wcs.crval[0], crval2 = wcs.crval[1], crpix1 = wcs.crpix[0], crpix2 = wcs.crpix[1], cd11 = wcs.cd[0], cd12 = wcs.cd[1], cd21 = wcs.cd[2], cd22 = wcs.cd[3], imagew = wcs.imagew, imageh = wcs.imageh) result = self.send_request(service, {'wcs':params}) print 'Result status:', result['status'] plotdata = result['plot'] plotdata = base64.b64decode(plotdata) open(outfn, 'wb').write(plotdata) print 'Wrote', outfn def sdss_plot(self, outfn, wcsfn, wcsext=0): return self.overlay_plot('sdss_image_for_wcs', outfn, wcsfn, wcsext) def galex_plot(self, outfn, wcsfn, wcsext=0): return self.overlay_plot('galex_image_for_wcs', outfn, wcsfn, wcsext) def myjobs(self): result = self.send_request('myjobs/') return result['jobs'] def job_status(self, job_id, justdict=False): result = self.send_request('jobs/%s' % job_id) if justdict: return result stat = result.get('status') if stat == 'success': result = self.send_request('jobs/%s/calibration' % job_id) print 'Calibration:', result result = self.send_request('jobs/%s/tags' % job_id) print 'Tags:', result result = self.send_request('jobs/%s/machine_tags' % job_id) print 'Machine Tags:', result result = self.send_request('jobs/%s/objects_in_field' % job_id) print 'Objects in field:', result result = self.send_request('jobs/%s/annotations' % job_id) print 'Annotations:', result result = self.send_request('jobs/%s/info' % job_id) print 'Calibration:', result return stat def sub_status(self, sub_id, justdict=False): result = self.send_request('submissions/%s' % sub_id) if justdict: return result return result.get('status') def jobs_by_tag(self, tag, exact): exact_option = 'exact=yes' if exact else '' result = self.send_request( 'jobs_by_tag?query=%s&%s' % (quote(tag.strip()), exact_option), {}, ) return result if __name__ == '__main__': import optparse parser = optparse.OptionParser() parser.add_option('--server', dest='server', default=Client.default_url, help='Set server base URL (eg, %default)') parser.add_option('--apikey', '-k', dest='apikey', help='API key for Astrometry.net web service; if not given will check AN_API_KEY environment variable') parser.add_option('--upload', '-u', dest='upload', help='Upload a file') parser.add_option('--wait', '-w', dest='wait', action='store_true', help='After submitting, monitor job status') parser.add_option('--wcs', dest='wcs', help='Download resulting wcs.fits file, saving to given filename; implies --wait if --urlupload or --upload') parser.add_option('--kmz', dest='kmz', help='Download resulting kmz file, saving to given filename; implies --wait if --urlupload or --upload') parser.add_option('--urlupload', '-U', dest='upload_url', help='Upload a file at specified url') parser.add_option('--scale-units', dest='scale_units', choices=('arcsecperpix', 'arcminwidth', 'degwidth', 'focalmm'), help='Units for scale estimate') #parser.add_option('--scale-type', dest='scale_type', # choices=('ul', 'ev'), help='Scale bounds: lower/upper or estimate/error') parser.add_option('--scale-lower', dest='scale_lower', type=float, help='Scale lower-bound') parser.add_option('--scale-upper', dest='scale_upper', type=float, help='Scale upper-bound') parser.add_option('--scale-est', dest='scale_est', type=float, help='Scale estimate') parser.add_option('--scale-err', dest='scale_err', type=float, help='Scale estimate error (in PERCENT), eg "10" if you estimate can be off by 10%') parser.add_option('--ra', dest='center_ra', type=float, help='RA center') parser.add_option('--dec', dest='center_dec', type=float, help='Dec center') parser.add_option('--radius', dest='radius', type=float, help='Search radius around RA,Dec center') parser.add_option('--downsample', dest='downsample_factor', type=int, help='Downsample image by this factor') parser.add_option('--parity', dest='parity', choices=('0','1'), help='Parity (flip) of image') parser.add_option('--tweak-order', dest='tweak_order', type=int, help='SIP distortion order (default: 2)') parser.add_option('--crpix-center', dest='crpix_center', action='store_true', default=None, help='Set reference point to center of image?') parser.add_option('--sdss', dest='sdss_wcs', nargs=2, help='Plot SDSS image for the given WCS file; write plot to given PNG filename') parser.add_option('--galex', dest='galex_wcs', nargs=2, help='Plot GALEX image for the given WCS file; write plot to given PNG filename') parser.add_option('--substatus', '-s', dest='sub_id', help='Get status of a submission') parser.add_option('--jobstatus', '-j', dest='job_id', help='Get status of a job') parser.add_option('--jobs', '-J', dest='myjobs', action='store_true', help='Get all my jobs') parser.add_option('--jobsbyexacttag', '-T', dest='jobs_by_exact_tag', help='Get a list of jobs associated with a given tag--exact match') parser.add_option('--jobsbytag', '-t', dest='jobs_by_tag', help='Get a list of jobs associated with a given tag') parser.add_option( '--private', '-p', dest='public', action='store_const', const='n', default='y', help='Hide this submission from other users') parser.add_option('--allow_mod_sa','-m', dest='allow_mod', action='store_const', const='sa', default='d', help='Select license to allow derivative works of submission, but only if shared under same conditions of original license') parser.add_option('--no_mod','-M', dest='allow_mod', action='store_const', const='n', default='d', help='Select license to disallow derivative works of submission') parser.add_option('--no_commercial','-c', dest='allow_commercial', action='store_const', const='n', default='d', help='Select license to disallow commercial use of submission') opt,args = parser.parse_args() if opt.apikey is None: # try the environment opt.apikey = os.environ.get('AN_API_KEY', None) if opt.apikey is None: parser.print_help() print print 'You must either specify --apikey or set AN_API_KEY' sys.exit(-1) args = {} args['apiurl'] = opt.server c = Client(**args) c.login(opt.apikey) if opt.upload or opt.upload_url: if opt.wcs or opt.kmz: opt.wait = True kwargs = dict( allow_commercial_use=opt.allow_commercial, allow_modifications=opt.allow_mod, publicly_visible=opt.public) if opt.scale_lower and opt.scale_upper: kwargs.update(scale_lower=opt.scale_lower, scale_upper=opt.scale_upper, scale_type='ul') elif opt.scale_est and opt.scale_err: kwargs.update(scale_est=opt.scale_est, scale_err=opt.scale_err, scale_type='ev') elif opt.scale_lower or opt.scale_upper: kwargs.update(scale_type='ul') if opt.scale_lower: kwargs.update(scale_lower=opt.scale_lower) if opt.scale_upper: kwargs.update(scale_upper=opt.scale_upper) for key in ['scale_units', 'center_ra', 'center_dec', 'radius', 'downsample_factor', 'tweak_order', 'crpix_center',]: if getattr(opt, key) is not None: kwargs[key] = getattr(opt, key) if opt.parity is not None: kwargs.update(parity=int(opt.parity)) if opt.upload: upres = c.upload(opt.upload, **kwargs) if opt.upload_url: upres = c.url_upload(opt.upload_url, **kwargs) stat = upres['status'] if stat != 'success': print 'Upload failed: status', stat print upres sys.exit(-1) opt.sub_id = upres['subid'] if opt.wait: if opt.job_id is None: if opt.sub_id is None: print "Can't --wait without a submission id or job id!" sys.exit(-1) while True: stat = c.sub_status(opt.sub_id, justdict=True) print 'Got status:', stat jobs = stat.get('jobs', []) if len(jobs): for j in jobs: if j is not None: break if j is not None: print 'Selecting job id', j opt.job_id = j break time.sleep(5) success = False while True: stat = c.job_status(opt.job_id, justdict=True) print 'Got job status:', stat if stat.get('status','') in ['success']: success = (stat['status'] == 'success') break time.sleep(5) if success: c.job_status(opt.job_id) # result = c.send_request('jobs/%s/calibration' % opt.job_id) # print 'Calibration:', result # result = c.send_request('jobs/%s/tags' % opt.job_id) # print 'Tags:', result # result = c.send_request('jobs/%s/machine_tags' % opt.job_id) # print 'Machine Tags:', result # result = c.send_request('jobs/%s/objects_in_field' % opt.job_id) # print 'Objects in field:', result #result = c.send_request('jobs/%s/annotations' % opt.job_id) #print 'Annotations:', result retrieveurls = [] if opt.wcs: # We don't need the API for this, just construct URL url = opt.server.replace('/api/', '/wcs_file/%i' % opt.job_id) retrieveurls.append((url, opt.wcs)) if opt.kmz: url = opt.server.replace('/api/', '/kml_file/%i/' % opt.job_id) retrieveurls.append((url, opt.kmz)) for url,fn in retrieveurls: print 'Retrieving file from', url, 'to', fn f = urlopen(url) txt = f.read() w = open(fn, 'wb') w.write(txt) w.close() print 'Wrote to', fn opt.job_id = None opt.sub_id = None if opt.sdss_wcs: (wcsfn, outfn) = opt.sdss_wcs c.sdss_plot(outfn, wcsfn) if opt.galex_wcs: (wcsfn, outfn) = opt.galex_wcs c.galex_plot(outfn, wcsfn) if opt.sub_id: print c.sub_status(opt.sub_id) if opt.job_id: print c.job_status(opt.job_id) #result = c.send_request('jobs/%s/annotations' % opt.job_id) #print 'Annotations:', result if opt.jobs_by_tag: tag = opt.jobs_by_tag print c.jobs_by_tag(tag, None) if opt.jobs_by_exact_tag: tag = opt.jobs_by_exact_tag print c.jobs_by_tag(tag, 'yes') if opt.myjobs: jobs = c.myjobs() print jobs #print c.submission_images(1)
No, there is no clean way to do so. When the module is being imported, it's code is executed and all global variables are set as attributes to the module object. So if part of the code is not executed at all (is guarded by __main__ condition) there is no clean way to get access to that code. You can however run code of this module with substituted __name__ but that's very hackish. You should refactor this module and move whole __main__ part into a method and call it like this: def main(): do_everything() if __name__ == '__main__': main() This way consumer apps will be able to run code without having to run it in a separate process.
Use the runpy module in the Python 3 Standard Library See that data can be passed to and from the called script # top.py import runpy import sys sys.argv += ["another parameter"] module_globals_dict = runpy.run_path("other_script.py", init_globals = globals(), run_name="__main__") print(module_globals_dict["return_value"]) # other_script.py # Note we did not load sys module, it gets passed to this script script_name = sys.argv[0] print(f"Script {script_name} loaded") if __name__ == "__main__": params = sys.argv[1:] print(f"Script {script_name} run with params: {params}") return_value = f"{script_name} Done"
by what your saying you want to call a function in the script that is importing the module so try: import __main__ __main__.myfunc()
How can I use rapportive.py in django
I am using rapportive in my python django projects. I am getting an error saying no information found The file is listed below: import sys import logging from textwrap import dedent # Requests, from python-requests.org from docopt import docopt # pylint: disable=C0103 logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) # pylint: enable=C0103 STATUS_URL = 'https://rapportive.com/login_status?user_email={0}' URL = 'https://profiles.rapportive.com/contacts/email/{0}' # pylint: disable=R0903 class Profile(object): """ Profile object for collecting profile information before printing """ def __init__(self, person): if person: self.name = person.get('name') self.jobinfo = [ (occupation.get('job_title'), occupation.get('company')) for occupation in person.get('occupations', []) ] self.memberships = [ (membership.get('site_name'), membership.get('profile_url')) for membership in person.get('memberships', []) ] self.success = person.get('success') def __str__(self): return dedent(""" Name: {0} {1} {2} """).format( self.name, "\n".join( "{0} {1}".format(title, company) for title, company in self.jobinfo), "\n".join( "\t{0} {1}".format(site_name, url) for site_name, url in self.memberships) ) def request(email): ''' rapportive_request(email): Sends a query to the undocumented Rapportive API Returns the response as a dict ''' status_url = STATUS_URL.format(email) response = requests.get(status_url).json() session_token = response.get('session_token') # fail gracefully if there is an error if 'error' in response: return response['error'] elif response['status'] == 200 and session_token: logger.debug('Session token: {0}'.format(session_token)) url = URL.format(email) headers = {'X-Session-Token': session_token} response = requests.get(url, headers=headers).json() if response.get('success') != 'nothing_useful': return Profile(response.get('contact')) return {} def ___process_email(email, output_file=None): """ Find email address in rapportive and print profile info if found """ profile = request(email) if profile and profile.success != 'nothing_useful': logger.info('Found match for {0}'.format(email)) print(profile) if output_file: output_file.write(summary + '\n') else: print("No information found\n") def main(): ''' main(): Expect a list of email addresses via stdin and check them with the Rapportive API ''' options = docopt(__doc__, version="0.1.0") logging.basicConfig( format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', datefmt='%m-%d %H:%M') if options["--verbose"]: logger.setLevel(logging.DEBUG) email = options.get("--email") args = [email] if email else [line.rstrip() for line in sys.stdin] output = options.get("--output") output = output and open(output, "w") for arg in args: ___process_email(arg, output) if __name__ == '__main__': main()
It seems working on my machine. Just a few things: the import request seems missing in the function ___process_email the summary variable in not define, I suppose it's summary = str(profile) an error in the indentation return Profile(response.get('contact') You got your error form the request function, the if response.get('success') != 'nothing_useful' must always be False. Have you seen this blog - there are some examples and some emails that's can be used. I used this one and I go a result jmwright798#gmail.com
Why wont my Simple CGI Server handle AJAX Post requests?
I have created my own CGI python server script (that serves on port 8000) by following a tutorial. The server works beautifully if I want to generate web pages from python scripts, or serve a native HTML page BUT it doesn't work for when I make an AJAX POST request? If I make an AJAX request to the python file aaa.py (using the javascript below) my server prints out the following error text: Code 501, message can only POST to to CGI scripts "POST /aaa.py HTTP/1.1" 501 - What do you think I need to do to allow my python cgi server to allow/handle AJAX requests? My CGI server: __version__ = "0.4" __all__ = ["CGIHTTPRequestHandler"] import os import sys import urllib import BaseHTTPServer import SimpleHTTPServer import select class CGIHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): """Complete HTTP server with GET, HEAD and POST commands. GET and HEAD also support running CGI scripts. The POST command is *only* implemented for CGI scripts. """ # Determine platform specifics have_fork = hasattr(os, 'fork') have_popen2 = hasattr(os, 'popen2') have_popen3 = hasattr(os, 'popen3') # pretend we don't have these to force execution in process have_fork = 0 # Make rfile unbuffered -- we need to read one line and then pass # the rest to a subprocess, so we can't use buffered input. rbufsize = 0 def do_POST(self): """Serve a POST request. This is only implemented for CGI scripts. """ if self.is_cgi(): self.run_cgi() else: self.send_error(501, "Can only POST to CGI scripts") def send_head(self): """Version of send_head that support CGI scripts""" if self.is_cgi(): return self.run_cgi() else: return SimpleHTTPServer.SimpleHTTPRequestHandler.send_head(self) def is_cgi(self): """Test whether self.path corresponds to a CGI script. Return a tuple (dir, rest) if self.path requires running a CGI script, None if not. Note that rest begins with a slash if it is not empty. The default implementation tests whether the path begins with one of the strings in the list self.cgi_directories (and the next character is a '/' or the end of the string). """ path = self.path for x in self.cgi_directories: i = len(x) if path[:i] == x and (not path[i:] or path[i] == '/'): self.cgi_info = path[:i], path[i+1:] return True return False cgi_directories = ['/cgi-bin', '/htbin'] def is_executable(self, path): """Test whether argument path is an executable file.""" return executable(path) def is_python(self, path): """Test whether argument path is a Python script.""" head, tail = os.path.splitext(path) return tail.lower() in (".py", ".pyw") def run_cgi(self): """Execute a CGI script.""" dir, rest = self.cgi_info i = rest.rfind('?') if i >= 0: rest, query = rest[:i], rest[i+1:] else: query = '' # i = rest.find('/') # if i >= 0: # script, rest = rest[:i], rest[i:] # else: # script, rest = rest, '' script = rest scriptname = dir + '/' + script scriptfile = self.translate_path(scriptname) if not os.path.exists(scriptfile): self.send_error(404, "No such CGI script (%s)" % `scriptname`) return if not os.path.isfile(scriptfile): self.send_error(403, "CGI script is not a plain file (%s)" % `scriptname`) return ispy = self.is_python(scriptname) if not ispy: if not (self.have_fork or self.have_popen2 or self.have_popen3): self.send_error(403, "CGI script is not a Python script (%s)" % `scriptname`) return if not self.is_executable(scriptfile): self.send_error(403, "CGI script is not executable (%s)" % `scriptname`) return # Reference: http://hoohoo.ncsa.uiuc.edu/cgi/env.html # XXX Much of the following could be prepared ahead of time! env = {} env['SERVER_SOFTWARE'] = self.version_string() env['SERVER_NAME'] = self.server.server_name env['GATEWAY_INTERFACE'] = 'CGI/1.1' env['SERVER_PROTOCOL'] = self.protocol_version env['SERVER_PORT'] = str(self.server.server_port) env['REQUEST_METHOD'] = self.command uqrest = urllib.unquote(rest) env['PATH_INFO'] = uqrest env['PATH_TRANSLATED'] = self.translate_path(uqrest) env['SCRIPT_NAME'] = scriptname if query: env['QUERY_STRING'] = query host = self.address_string() if host != self.client_address[0]: env['REMOTE_HOST'] = host env['REMOTE_ADDR'] = self.client_address[0] # XXX AUTH_TYPE # XXX REMOTE_USER # XXX REMOTE_IDENT if self.headers.typeheader is None: env['CONTENT_TYPE'] = self.headers.type else: env['CONTENT_TYPE'] = self.headers.typeheader length = self.headers.getheader('content-length') if length: env['CONTENT_LENGTH'] = length accept = [] for line in self.headers.getallmatchingheaders('accept'): if line[:1] in "\t\n\r ": accept.append(line.strip()) else: accept = accept + line[7:].split(',') env['HTTP_ACCEPT'] = ','.join(accept) ua = self.headers.getheader('user-agent') if ua: env['HTTP_USER_AGENT'] = ua co = filter(None, self.headers.getheaders('cookie')) if co: env['HTTP_COOKIE'] = ', '.join(co) # XXX Other HTTP_* headers if not self.have_fork: # Since we're setting the env in the parent, provide empty # values to override previously set values for k in ('QUERY_STRING', 'REMOTE_HOST', 'CONTENT_LENGTH', 'HTTP_USER_AGENT'): ###, 'HTTP_COOKIE' -- removed by S. env.setdefault(k, "") # for key in env.keys(): # print key + " '" + env[key] + "'" os.environ.update(env) self.send_response(200, "Script output follows") decoded_query = query.replace('+', ' ') if self.have_fork: # Unix -- fork as we should args = [script] if '=' not in decoded_query: args.append(decoded_query) nobody = nobody_uid() self.wfile.flush() # Always flush before forking pid = os.fork() if pid != 0: # Parent pid, sts = os.waitpid(pid, 0) # throw away additional data [see bug #427345] while select.select([self.rfile], [], [], 0)[0]: if not self.rfile.read(1): break if sts: self.log_error("CGI script exit status %#x", sts) return # Child try: try: os.setuid(nobody) except os.error: pass os.dup2(self.rfile.fileno(), 0) os.dup2(self.wfile.fileno(), 1) os.execve(scriptfile, args, os.environ) except: self.server.handle_error(self.request, self.client_address) os._exit(127) elif self.have_popen2 or self.have_popen3: # Windows -- use popen2 or popen3 to create a subprocess import shutil if self.have_popen3: popenx = os.popen3 else: popenx = os.popen2 cmdline = scriptfile if self.is_python(scriptfile): interp = sys.executable if interp.lower().endswith("w.exe"): # On Windows, use python.exe, not pythonw.exe interp = interp[:-5] + interp[-4:] cmdline = "%s -u \"%s\"" % (interp, cmdline) if '=' not in query and '"' not in query: cmdline = '%s "%s"' % (cmdline, query) self.log_message("command: %s", cmdline) try: nbytes = int(length) except (TypeError, ValueError): nbytes = 0 files = popenx(cmdline, 'b') fi = files[0] fo = files[1] if self.have_popen3: fe = files[2] if self.command.lower() == "post" and nbytes > 0: data = self.rfile.read(nbytes) fi.write(data) # throw away additional data [see bug #427345] while select.select([self.rfile._sock], [], [], 0)[0]: if not self.rfile._sock.recv(1): break fi.close() shutil.copyfileobj(fo, self.wfile) if self.have_popen3: errors = fe.read() fe.close() if errors: self.log_error('%s', errors) sts = fo.close() if sts: self.log_error("CGI script exit status %#x", sts) else: self.log_message("CGI script exited OK") else: # Other O.S. -- execute script in this process save_argv = sys.argv save_stdin = sys.stdin save_stdout = sys.stdout save_stderr = sys.stderr try: try: sys.argv = [scriptfile] if '=' not in decoded_query: sys.argv.append(decoded_query) sys.stdout = self.wfile sys.stdin = self.rfile execfile(scriptfile, {"__name__": "__main__"}) finally: sys.argv = save_argv sys.stdin = save_stdin sys.stdout = save_stdout sys.stderr = save_stderr except SystemExit, sts: self.log_error("CGI script exit status %s", str(sts)) else: self.log_message("CGI script exited OK") nobody = None def nobody_uid(): """Internal routine to get nobody's uid""" global nobody if nobody: return nobody try: import pwd except ImportError: return -1 try: nobody = pwd.getpwnam('nobody')[2] except KeyError: nobody = 1 + max(map(lambda x: x[2], pwd.getpwall())) return nobody def executable(path): """Test for executable file.""" try: st = os.stat(path) except os.error: return False return st.st_mode & 0111 != 0 def test(HandlerClass = CGIHTTPRequestHandler, ServerClass = BaseHTTPServer.HTTPServer): SimpleHTTPServer.test(HandlerClass, ServerClass) if __name__ == '__main__': test() Code in aaa.py: #!/usr/bin/env python import cgitb; cgitb.enable() import cgi import os print "Content-Type: text/html\n" input_data = cgi.FieldStorage() print "hello" My AJAX/ Javascript: function onTest( dest, params ) { var xmlhttp; if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari xmlhttp=new XMLHttpRequest(); } else {// code for IE6, IE5 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4 && xmlhttp.status==200) { document.getElementById( "bb" ).innerHTML = xmlhttp.responseText; } } xmlhttp.open("POST",dest,true); xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded"); xmlhttp.send( params ); }
when you use the python http cgi server, cgi scripts have to be under the subdir (from you server script ) /cgi-bin